Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a7282ac

Browse files
author
Oscar Gustafsson
committed
All classes and methods in dates support both string and tzinfo as tz-argument
1 parent ff79835 commit a7282ac

File tree

3 files changed

+117
-71
lines changed

3 files changed

+117
-71
lines changed

lib/matplotlib/dates.py

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""
22
Matplotlib 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
55
By default, Matplotlib uses the units machinery described in
66
`~matplotlib.units` to convert `datetime.datetime`, and `numpy.datetime64`
@@ -83,10 +83,11 @@
8383
Out[1]: 732401
8484
8585
All 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 custom timezone, pass a `datetime.tzinfo`
88+
instance or a string with the timezone name to the tz keyword argument of
89+
`num2date`, `.Axis.axis_date`, and any custom date tickers or locators you
90+
create. Timezone strings are parsed by `~dateutil.tz.gettz`.
9091
9192
A wide range of specific and general purpose date tick locators and
9293
formatters are provided in this module. See
@@ -141,10 +142,10 @@
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
@@ -202,12 +203,24 @@
202203
UTC = 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

645654
class 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

15401547
class 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

15681575
class 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

15941601
class 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

16141621
class 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

16341641
class 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

16541661
class MicrosecondLocator(DateLocator):

0 commit comments

Comments
 (0)