@@ -308,16 +308,16 @@ def get_epoch():
308308 return _epoch
309309
310310
311- def _dt64_to_ordinalf (d , * , is_timedelta = False ):
311+ def _to_ordinalf (d , * , is_timedelta = False ):
312312 """
313313 Convert `numpy.datetime64` or an `numpy.ndarray` of those types to
314314 Gregorian date as UTC float relative to the epoch (see `.get_epoch`).
315315 Roundoff is float64 precision. Practically: microseconds for dates
316316 between 290301 BC, 294241 AD, milliseconds for larger dates
317317 (see `numpy.datetime64`).
318- `is_timedelta` indicates that the converted values are timedelta instead
319- of datetime . The converted floating point timedelta values are relative
320- to `timedelta(0)`.
318+ If `is_timedelta=True`, converts `numpy.timedelta64` or an `numpy.ndarray`
319+ of those types to float . The converted floating point timedelta values are
320+ relative to `timedelta(0)`.
321321 """
322322
323323 # the "extra" ensures that we at least allow the dynamic range out to
@@ -336,11 +336,7 @@ def _dt64_to_ordinalf(d, *, is_timedelta=False):
336336
337337 NaT_int = np .datetime64 ('NaT' ).astype (np .int64 )
338338 t_int = d .astype (np .int64 )
339- try :
340- dt [t_int == NaT_int ] = np .nan
341- except TypeError :
342- if t_int == NaT_int :
343- dt = np .nan
339+ dt [t_int == NaT_int ] = np .nan
344340
345341 return dt
346342
@@ -486,7 +482,7 @@ def _timevalue2num(v, *, is_timedelta=False):
486482 elif not is_timedelta and not np .issubdtype (v .dtype , np .datetime64 ):
487483 # datetime arrays
488484 if not v .size :
489- # deals with an empty array...
485+ # deals with an empty array; only required for datetime
490486 return v
491487 tzi = getattr (v [0 ], 'tzinfo' , None )
492488 if tzi is not None :
@@ -496,7 +492,7 @@ def _timevalue2num(v, *, is_timedelta=False):
496492 v = v .astype ('datetime64[us]' )
497493
498494 v = np .ma .masked_array (v , mask = mask ) if masked else v
499- v = _dt64_to_ordinalf (v , is_timedelta = is_timedelta )
495+ v = _to_ordinalf (v , is_timedelta = is_timedelta )
500496
501497 return v if iterable else v [0 ]
502498
@@ -704,8 +700,10 @@ def strftimedelta(td, fmt_str):
704700
705701 try :
706702 result = _TimedeltaFormatTemplate (fmt_str ).substitute (** values )
707- except KeyError :
708- raise ValueError (f"Invalid format string '{ fmt_str } ' for timedelta" )
703+ except ValueError as exc :
704+ # show a more understandable error message
705+ exc .args = (f"Invalid format string '{ fmt_str } ' for timedelta" , )
706+ raise exc
709707 return sign + result
710708
711709
@@ -785,6 +783,7 @@ def __init__(self, locator, show_offset=True, *, usetex=None):
785783 self .offset_string = ''
786784 self .show_offset = show_offset
787785 self ._usetex = mpl ._val_or_rc (usetex , 'text.usetex' )
786+ self ._zerovals = [None , None , None , None , None , None , None ]
788787
789788 self .formats = list ()
790789 self .zero_formats = list ()
@@ -826,11 +825,10 @@ def _format_ticks(self, tickvalue, ticktuple):
826825
827826 # level is the basic level we will label at.
828827 # now loop through and decide the actual ticklabels
829- zerovals = [0 , 1 , 1 , 0 , 0 , 0 , 0 ]
830828 labels = ['' ] * len (ticktuple )
831829 for nn in range (len (ticktuple )):
832830 if level < 5 :
833- if ticktuple [nn ][level ] == zerovals [level ]:
831+ if ticktuple [nn ][level ] == self . _zerovals [level ]:
834832 fmt = zerofmts [level ]
835833 else :
836834 fmt = fmts [level ]
@@ -964,6 +962,9 @@ def __init__(self, locator, tz=None, formats=None, offset_formats=None,
964962 """
965963 super ().__init__ (locator , show_offset = show_offset , usetex = usetex )
966964 self ._tz = tz
965+ # zerovals are values that are zeros for a given tick level, for dates,
966+ # months and days start at 1, while hours, minutes, ... start at 0
967+ self ._zerovals = [0 , 1 , 1 , 0 , 0 , 0 , 0 ]
967968 self .defaultfmt = '%Y'
968969 # there are 6 levels with each level getting a specific format
969970 # 0: mostly years, 1: months, 2: days,
@@ -1038,7 +1039,10 @@ def __init__(self, locator, formats=None, offset_formats=None,
10381039 initial string, and then redundant elements are removed.
10391040 """
10401041 super ().__init__ (locator , show_offset = show_offset , usetex = usetex )
1041- self .defaultfmt = '%{d}D'
1042+ # zerovals are values that are zeros for a given tick level. For
1043+ # timedelta, this is always 0
1044+ self ._zerovals = [0 , 0 , 0 , 0 , 0 , 0 , 0 ]
1045+ self .defaultfmt = '%d d'
10421046 # there are 6 levels with each level getting a specific format
10431047 # 0: mostly years, 1: months, 2: days,
10441048 # 3: hours, 4: minutes, 5: seconds
@@ -1049,7 +1053,7 @@ def __init__(self, locator, formats=None, offset_formats=None,
10491053 '4 format strings (or None)' )
10501054 self .formats = formats
10511055 else :
1052- self .formats = ['%{d} days ' , # days
1056+ self .formats = ['%d d ' , # days
10531057 '%-H:%M' , # hours
10541058 '%-H:%M' , # minutes
10551059 '%-S.%f' , # secs
@@ -1064,7 +1068,7 @@ def __init__(self, locator, formats=None, offset_formats=None,
10641068 self .zero_formats = zero_formats
10651069 else :
10661070 # use the users formats for the zero tick formats
1067- self .zero_formats = ['' ] + self .formats [:- 1 ]
1071+ self .zero_formats = ['%d d ' ] + self .formats [:- 1 ]
10681072
10691073 if offset_formats :
10701074 if len (offset_formats ) != 4 :
@@ -1074,8 +1078,8 @@ def __init__(self, locator, formats=None, offset_formats=None,
10741078 else :
10751079 self .offset_formats = ['' ,
10761080 '' ,
1077- '%{d} days' ,
1078- '%{d} days %-H:%M' ]
1081+ '%d days' ,
1082+ '%d days %-H:%M' ]
10791083
10801084 def __call__ (self , x , pos = None ):
10811085 formatter = TimedeltaFormatter (self .defaultfmt , usetex = self ._usetex )
@@ -1107,7 +1111,7 @@ def format_ticks(self, values):
11071111 return super ()._format_ticks (ticktimedelta , ticktuple )
11081112
11091113 def format_data_short (self , value ):
1110- return strftimedelta (num2timedelta (value ), '%{d}D %H:%M:%S' )
1114+ return strftimedelta (num2timedelta (value ), '%d d %H:%M:%S' )
11111115
11121116 def _format_string (self , value , fmt ):
11131117 return strftimedelta (value , fmt )
@@ -2121,7 +2125,7 @@ class TimedeltaLocator(ticker.MultipleLocator):
21212125 locator = TimedeltaLocator(HOURLY, 4)
21222126 """
21232127 default_range = (timedelta2num (datetime .timedelta (days = 0 )),
2124- timedelta2num (datetime .timedelta (days = 10 )))
2128+ timedelta2num (datetime .timedelta (days = 1 )))
21252129 """The default min and max limits of the axis."""
21262130
21272131 _FACTORS = {
@@ -2293,6 +2297,7 @@ def update_from_limits(self, dmin, dmax):
22932297 break
22942298 break
22952299 else :
2300+ # prevent interval from being undefined in case intervald was empty
22962301 interval = 1
22972302 super ().set_params (freq = freq , interval = interval )
22982303
0 commit comments