11"""
22Matplotlib provides sophisticated date plotting capabilities, standing on the
3- shoulders of python :mod:`datetime` and the add-on module :mod:`dateutil` .
3+ shoulders of python :mod:`datetime` and the add-on module dateutil_ .
44
55By default, Matplotlib uses the units machinery described in
66`~matplotlib.units` to convert `datetime.datetime`, and `numpy.datetime64`
8383 Out[1]: 732401
8484
8585All the Matplotlib date converters, tickers and formatters are timezone aware.
86- If no explicit timezone is provided, :rc:`timezone` is assumed. If you want to
87- use a custom time zone, pass a `datetime.tzinfo` instance with the tz keyword
88- argument to `num2date`, `.Axis.axis_date`, and any custom date tickers or
89- locators you create.
86+ If no explicit timezone is provided, :rc:`timezone` is assumed, provided as a
87+ string. If you want to use a different timezone, pass the *tz* keyword
88+ argument of `num2date` to any date tickers or locators you create. This can
89+ be either a `datetime.tzinfo` instance or a string with the timezone name that
90+ can be parsed by `~dateutil.tz.gettz`.
9091
9192A wide range of specific and general purpose date tick locators and
9293formatters are provided in this module. See
141142
142143* `YearLocator`: Locate years that are multiples of base.
143144
144- * `RRuleLocator`: Locate using a `matplotlib.dates.rrulewrapper`.
145- `. rrulewrapper` is a simple wrapper around dateutil_'s `dateutil.rrule` which
146- allow almost arbitrary date tick specifications. See :doc:`rrule example
147- </gallery/ticks/date_demo_rrule>`.
145+ * `RRuleLocator`: Locate using a `` matplotlib.dates.rrulewrapper` `.
146+ `` rrulewrapper`` is a simple wrapper around dateutil_'s `dateutil.rrule`
147+ which allow almost arbitrary date tick specifications.
148+ See :doc:`rrule example </gallery/ticks/date_demo_rrule>`.
148149
149150* `AutoDateLocator`: On autoscale, this class picks the best `DateLocator`
150151 (e.g., `RRuleLocator`) to set the view limits and the tick locations. If
202203UTC = datetime .timezone .utc
203204
204205
205- def _get_rc_timezone ():
206- """Retrieve the preferred timezone from the rcParams dictionary."""
207- s = mpl .rcParams ['timezone' ]
208- if s == 'UTC' :
209- return UTC
210- return dateutil .tz .gettz (s )
206+ def _get_tzinfo (tz = None ):
207+ """
208+ Generate tzinfo from a string or return tzinfo. If None,
209+ retrieve the preferred timezone from the rcParams dictionary.
210+ """
211+ if tz is None :
212+ tz = mpl .rcParams ['timezone' ]
213+ if tz == 'UTC' :
214+ return UTC
215+ if isinstance (tz , str ):
216+ tzinfo = dateutil .tz .gettz (tz )
217+ if tzinfo is None :
218+ raise ValueError (f"{ tz } is not a valid timezone as parsed by"
219+ " dateutil.tz.gettz." )
220+ return tzinfo
221+ if isinstance (tz , datetime .tzinfo ):
222+ return tz
223+ raise TypeError ("tz must be string or tzinfo subclass." )
211224
212225
213226"""
@@ -341,8 +354,7 @@ def _from_ordinalf(x, tz=None):
341354 :rc:`timezone`.
342355 """
343356
344- if tz is None :
345- tz = _get_rc_timezone ()
357+ tz = _get_tzinfo (tz )
346358
347359 dt = (np .datetime64 (get_epoch ()) +
348360 np .timedelta64 (int (np .round (x * MUSECONDS_PER_DAY )), 'us' ))
@@ -508,8 +520,8 @@ def num2date(x, tz=None):
508520 Number of days (fraction part represents hours, minutes, seconds)
509521 since the epoch. See `.get_epoch` for the
510522 epoch, which can be changed by :rc:`date.epoch` or `.set_epoch`.
511- tz : str, default: :rc:`timezone`
512- Timezone of *x*.
523+ tz : str or `~datetime.tzinfo` , default: :rc:`timezone`
524+ Timezone of *x*. If a string, *tz* is passed to `dateutil.tz`.
513525
514526 Returns
515527 -------
@@ -525,8 +537,7 @@ def num2date(x, tz=None):
525537 Gregorian calendar is assumed; this is not universal practice.
526538 For details, see the module docstring.
527539 """
528- if tz is None :
529- tz = _get_rc_timezone ()
540+ tz = _get_tzinfo (tz )
530541 return _from_ordinalf_np_vectorized (x , tz ).tolist ()
531542
532543
@@ -621,16 +632,14 @@ def __init__(self, fmt, tz=None, *, usetex=None):
621632 ----------
622633 fmt : str
623634 `~datetime.datetime.strftime` format string
624- tz : ` datetime.tzinfo`, default: :rc:`timezone`
635+ tz : str or `~ datetime.tzinfo`, default: :rc:`timezone`
625636 Ticks timezone.
626637 usetex : bool, default: :rc:`text.usetex`
627638 To enable/disable the use of TeX's math mode for rendering the
628639 results of the formatter.
629640 """
630- if tz is None :
631- tz = _get_rc_timezone ()
641+ self .tz = _get_tzinfo (tz )
632642 self .fmt = fmt
633- self .tz = tz
634643 self ._usetex = (usetex if usetex is not None else
635644 mpl .rcParams ['text.usetex' ])
636645
@@ -639,7 +648,7 @@ def __call__(self, x, pos=0):
639648 return _wrap_in_tex (result ) if self ._usetex else result
640649
641650 def set_tzinfo (self , tz ):
642- self .tz = tz
651+ self .tz = _get_tzinfo ( tz )
643652
644653
645654class ConciseDateFormatter (ticker .Formatter ):
@@ -656,8 +665,8 @@ class ConciseDateFormatter(ticker.Formatter):
656665 locator : `.ticker.Locator`
657666 Locator that this axis is using.
658667
659- tz : str, optional
660- Passed to `.dates.date2num `.
668+ tz : str or `~datetime.tzinfo`, default: :rc:`timezone`
669+ Passed to `.dates.num2date `.
661670
662671 formats : list of 6 strings, optional
663672 Format strings for 6 levels of tick labelling: mostly years,
@@ -757,7 +766,7 @@ def __init__(self, locator, tz=None, formats=None, offset_formats=None,
757766
758767 if offset_formats :
759768 if len (offset_formats ) != 6 :
760- raise ValueError ('offsetfmts argument must be a list of '
769+ raise ValueError ('offset_formats argument must be a list of '
761770 '6 format strings (or None)' )
762771 self .offset_formats = offset_formats
763772 else :
@@ -927,8 +936,8 @@ def __init__(self, locator, tz=None, defaultfmt='%Y-%m-%d', *,
927936 locator : `.ticker.Locator`
928937 Locator that this axis is using.
929938
930- tz : str, optional
931- Passed to `.dates.date2num `.
939+ tz : str or `~datetime.tzinfo` , optional
940+ Passed to `.dates.num2date `.
932941
933942 defaultfmt : str
934943 The default format to use if none of the values in ``self.scaled``
@@ -1000,7 +1009,7 @@ def set(self, **kwargs):
10001009 def _update_rrule (self , ** kwargs ):
10011010 tzinfo = self ._base_tzinfo
10021011
1003- # rrule does not play nicely with time zones - especially pytz time
1012+ # rrule does not play nicely with timezones - especially pytz time
10041013 # zones, it's best to use naive zones and attach timezones once the
10051014 # datetimes are returned
10061015 if 'dtstart' in kwargs :
@@ -1103,17 +1112,15 @@ def __init__(self, tz=None):
11031112 """
11041113 Parameters
11051114 ----------
1106- tz : ` datetime.tzinfo`
1115+ tz : str or `~ datetime.tzinfo`, default: :rc:`timezone `
11071116 """
1108- if tz is None :
1109- tz = _get_rc_timezone ()
1110- self .tz = tz
1117+ self .tz = _get_tzinfo (tz )
11111118
11121119 def set_tzinfo (self , tz ):
11131120 """
1114- Set time zone info.
1121+ Set timezone info. str or `~datetime.tzinfo` .
11151122 """
1116- self .tz = tz
1123+ self .tz = _get_tzinfo ( tz )
11171124
11181125 def datalim_to_dt (self ):
11191126 """Convert axis data interval to datetime objects."""
@@ -1283,7 +1290,7 @@ def __init__(self, tz=None, minticks=5, maxticks=None,
12831290 """
12841291 Parameters
12851292 ----------
1286- tz : ` datetime.tzinfo`
1293+ tz : str or `~ datetime.tzinfo`, default: :rc:`timezone `
12871294 Ticks timezone.
12881295 minticks : int
12891296 The minimum number of ticks desired; controls whether ticks occur
@@ -1303,7 +1310,7 @@ def __init__(self, tz=None, minticks=5, maxticks=None,
13031310 the ticks to be at hours 0, 6, 12, 18 when hourly ticking is done
13041311 at 6 hour intervals.
13051312 """
1306- super ().__init__ (tz )
1313+ super ().__init__ (tz = tz )
13071314 self ._freq = YEARLY
13081315 self ._freqs = [YEARLY , MONTHLY , DAILY , HOURLY , MINUTELY ,
13091316 SECONDLY , MICROSECONDLY ]
@@ -1457,7 +1464,7 @@ def get_locator(self, dmin, dmax):
14571464 byhour = byhour , byminute = byminute ,
14581465 bysecond = bysecond )
14591466
1460- locator = RRuleLocator (rrule , self .tz )
1467+ locator = RRuleLocator (rrule , tz = self .tz )
14611468 else :
14621469 locator = MicrosecondLocator (interval , tz = self .tz )
14631470 if date2num (dmin ) > 70 * 365 and interval < 1000 :
@@ -1490,7 +1497,7 @@ def __init__(self, base=1, month=1, day=1, tz=None):
14901497 """
14911498 rule = rrulewrapper (YEARLY , interval = base , bymonth = month ,
14921499 bymonthday = day , ** self .hms0d )
1493- super ().__init__ (rule , tz )
1500+ super ().__init__ (rule , tz = tz )
14941501 self .base = ticker ._Edge_integer (base , 0 )
14951502
14961503 def _create_rrule (self , vmin , vmax ):
@@ -1534,7 +1541,7 @@ def __init__(self, bymonth=None, bymonthday=1, interval=1, tz=None):
15341541
15351542 rule = rrulewrapper (MONTHLY , bymonth = bymonth , bymonthday = bymonthday ,
15361543 interval = interval , ** self .hms0d )
1537- super ().__init__ (rule , tz )
1544+ super ().__init__ (rule , tz = tz )
15381545
15391546
15401547class WeekdayLocator (RRuleLocator ):
@@ -1562,7 +1569,7 @@ def __init__(self, byweekday=1, interval=1, tz=None):
15621569
15631570 rule = rrulewrapper (DAILY , byweekday = byweekday ,
15641571 interval = interval , ** self .hms0d )
1565- super ().__init__ (rule , tz )
1572+ super ().__init__ (rule , tz = tz )
15661573
15671574
15681575class DayLocator (RRuleLocator ):
@@ -1588,7 +1595,7 @@ def __init__(self, bymonthday=None, interval=1, tz=None):
15881595
15891596 rule = rrulewrapper (DAILY , bymonthday = bymonthday ,
15901597 interval = interval , ** self .hms0d )
1591- super ().__init__ (rule , tz )
1598+ super ().__init__ (rule , tz = tz )
15921599
15931600
15941601class HourLocator (RRuleLocator ):
@@ -1608,7 +1615,7 @@ def __init__(self, byhour=None, interval=1, tz=None):
16081615
16091616 rule = rrulewrapper (HOURLY , byhour = byhour , interval = interval ,
16101617 byminute = 0 , bysecond = 0 )
1611- super ().__init__ (rule , tz )
1618+ super ().__init__ (rule , tz = tz )
16121619
16131620
16141621class MinuteLocator (RRuleLocator ):
@@ -1628,7 +1635,7 @@ def __init__(self, byminute=None, interval=1, tz=None):
16281635
16291636 rule = rrulewrapper (MINUTELY , byminute = byminute , interval = interval ,
16301637 bysecond = 0 )
1631- super ().__init__ (rule , tz )
1638+ super ().__init__ (rule , tz = tz )
16321639
16331640
16341641class SecondLocator (RRuleLocator ):
@@ -1648,7 +1655,7 @@ def __init__(self, bysecond=None, interval=1, tz=None):
16481655 bysecond = range (60 )
16491656
16501657 rule = rrulewrapper (SECONDLY , bysecond = bysecond , interval = interval )
1651- super ().__init__ (rule , tz )
1658+ super ().__init__ (rule , tz = tz )
16521659
16531660
16541661class MicrosecondLocator (DateLocator ):
0 commit comments