8000 FIX: properly set tz for YearLocator · matplotlib/matplotlib@3219aa6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3219aa6

Browse files
committed
FIX: properly set tz for YearLocator
FIX: add check for py3.5 to fail if naive datetime TST: make pytz yearlylocator test
1 parent 7b40990 commit 3219aa6

File tree

2 files changed

+112
-6
lines changed

2 files changed

+112
-6
lines changed

lib/matplotlib/dates.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ def __init__(self, tz=None, minticks=5, maxticks=None,
14171417
locator.intervald[HOURLY] = [3] # only show every 3 hours
14181418
"""
14191419
DateLocator.__init__(self, tz)
1420-
self._locator = YearLocator()
1420+
self._locator = YearLocator(tz=tz)
14211421
self._freq = YEARLY
14221422
self._freqs = [YEARLY, MONTHLY, DAILY, HOURLY, MINUTELY,
14231423
SECONDLY, MICROSECONDLY]
@@ -1574,7 +1574,7 @@ def get_locator(self, dmin, dmax):
15741574
'AutoDateLocator.')
15751575

15761576
if (freq == YEARLY) and self.interval_multiples:
1577-
locator = YearLocator(interval)
1577+
locator = YearLocator(interval, tz=self.tz)
15781578
elif use_rrule_locator[i]:
15791579
_, bymonth, bymonthday, byhour, byminute, bysecond, _ = byranges
15801580
rrule = rrulewrapper(self._freq, interval=interval,
@@ -1623,8 +1623,10 @@ def __init__(self, base=1, month=1, day=1, tz=None):
16231623
'hour': 0,
16241624
'minute': 0,
16251625
'second': 0,
1626-
'tzinfo': tz
16271626
}
1627+
# Note that tzinfo does not work with pytz timezones, and
1628+
# astimezone doesn't work unless a datetime has timezone info (for
1629+
# py3.5). So the user should provide time-zone aware dates.
16281630

16291631
def __call__(self):
16301632
# if no data have been set, this will tank with a ValueError
@@ -1639,13 +1641,19 @@ def tick_values(self, vmin, vmax):
16391641
ymin = self.base.le(vmin.year) * self.base.step
16401642
ymax = self.base.ge(vmax.year) * self.base.step
16411643

1642-
ticks = [vmin.replace(year=ymin, **self.replaced)]
1644+
vmin = vmin.replace(year=ymin, **self.replaced)
1645+
try:
1646+
ticks = [vmin.astimezone(self.tz)]
1647+
except ValueError as e:
1648+
raise ValueError('naive datetime objects cannot be used '
1649+
'with matplotlib for python < 3.6; ') from e
16431650
while True:
16441651
dt = ticks[-1]
16451652
if dt.year >= ymax:
16461653
return date2num(ticks)
16471654
year = dt.year + self.base.step
1648-
ticks.append(dt.replace(year=year, **self.replaced))
1655+
dt = dt.replace(year=year, **self.replaced).astimezone(self.tz)
1656+
ticks.append(dt)
16491657

16501658
def autoscale(self):
16511659
"""
@@ -1656,7 +1664,9 @@ def autoscale(self):
16561664
ymin = self.base.le(dmin.year)
16571665
ymax = self.base.ge(dmax.year)
16581666
vmin = dmin.replace(year=ymin, **self.replaced)
1667+
vmin = vmin.astimezone(self.tz)
16591668
vmax = dmax.replace(year=ymax, **self.replaced)
1669+
vmax = vmax.astimezone(self.tz)
16601670

16611671
vmin = date2num(vmin)
16621672
vmax = date2num(vmax)

lib/matplotlib/tests/test_dates.py

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from matplotlib.cbook import MatplotlibDeprecationWarning
1313
import matplotlib.dates as mdates
1414
import matplotlib.ticker as mticker
15+
from matplotlib import rc_context
1516

1617

1718
def __has_pytz():
@@ -439,7 +440,6 @@ def _create_auto_date_locator(date1, date2):
439440
mdates.date2num(date2))
440441
return locator
441442

442-
d1 = datetime.datetime(1997, 1, 1)
443443
results = ([datetime.timedelta(weeks=52 * 200),
444444
['1980-01-01 00:00:00+00:00', '2000-01-01 00:00:00+00:00',
445445
'2020-01-01 00:00:00+00:00', '2040-01-01 00:00:00+00:00',
@@ -500,6 +500,7 @@ def _create_auto_date_locator(date1, date2):
500500
],
501501
)
502502

503+
d1 = datetime.datetime(1997, 1, 1)
503504
for t_delta, expected in results:
504505
d2 = d1 + t_delta
505506
locator = _create_auto_date_locator(d1, d2)
@@ -557,6 +558,77 @@ def _create_auto_date_locator(date1, date2):
557558
assert strings == expected
558559

559560

561+
def test_auto_date_locator_intmult_tz():
562+
def _create_auto_date_locator(date1, date2, tz):
563+
locator = mdates.AutoDateLocator(interval_multiples=True, tz=tz)
564+
locator.create_dummy_axis()
565+
locator.set_view_interval(mdates.date2num(date1),
566+
mdates.date2num(date2))
567+
return locator
568+
569+
results = ([datetime.timedelta(weeks=52*200),
570+
['1980-01-01 00:00:00-08:00', '2000-01-01 00:00:00-08:00',
571+
'2020-01-01 00:00:00-08:00', '2040-01-01 00:00:00-08:00',
572+
'2060-01-01 00:00:00-08:00', '2080-01-01 00:00:00-08:00',
573+
'2100-01-01 00:00:00-08:00', '2120-01-01 00:00:00-08:00',
574+
'2140-01-01 00:00:00-08:00', '2160-01-01 00:00:00-08:00',
575+
'2180-01-01 00:00:00-08:00', '2200-01-01 00:00:00-08:00']
576+
],
577+
[datetime.timedelta(weeks=52),
578+
['1997-01-01 00:00:00-08:00', '1997-02-01 00:00:00-08:00',
579+
'1997-03-01 00:00:00-08:00', '1997-04-01 00:00:00-08:00',
580+
'1997-05-01 00:00:00-07:00', '1997-06-01 00:00:00-07:00',
581+
'1997-07-01 00:00:00-07:00', '1997-08-01 00:00:00-07:00',
582+
'1997-09-01 00:00:00-07:00', '1997-10-01 00:00:00-07:00',
583+
'1997-11-01 00:00:00-08:00', '1997-12-01 00:00:00-08:00']
584+
],
585+
[datetime.timedelta(days=141),
586+
['1997-01-01 00:00:00-08:00', '1997-01-22 00:00:00-08:00',
587+
'1997-02-01 00:00:00-08:00', '1997-02-22 00:00:00-08:00',
588+
'1997-03-01 00:00:00-08:00', '1997-03-22 00:00:00-08:00',
589+
'1997-04-01 00:00:00-08:00', '1997-04-22 00:00:00-07:00',
590+
'1997-05-01 00:00:00-07:00', '1997-05-22 00:00:00-07:00']
591+
],
592+
[datetime.timedelta(days=40),
593+
['1997-01-01 00:00:00-08:00', '1997-01-05 00:00:00-08:00',
594+
'1997-01-09 00:00:00-08:00', '1997-01-13 00:00:00-08:00',
595+
'1997-01-17 00:00:00-08:00', '1997-01-21 00:00:00-08:00',
596+
'1997-01-25 00:00:00-08:00', '1997-01-29 00:00:00-08:00',
597+
'1997-02-01 00:00:00-08:00', '1997-02-05 00:00:00-08:00',
598+
'1997-02-09 00:00:00-08:00']
599+
],
600+
[datetime.timedelta(hours=40),
601+
['1997-01-01 00:00:00-08:00', '1997-01-01 04:00:00-08:00',
602+
'1997-01-01 08:00:00-08:00', '1997-01-01 12:00:00-08:00',
603+
'1997-01-01 16:00:00-08:00', '1997-01-01 20:00:00-08:00',
604+
'1997-01-02 00:00:00-08:00', '1997-01-02 04:00:00-08:00',
605+
'1997-01-02 08:00:00-08:00', '1997-01-02 12:00:00-08:00',
606+
'1997-01-02 16:00:00-08:00']
607+
],
608+
[datetime.timedelta(minutes=20),
609+
['1997-01-01 00:00:00-08:00', '1997-01-01 00:05:00-08:00',
610+
'1997-01-01 00:10:00-08:00', '1997-01-01 00:15:00-08:00',
611+
'1997-01-01 00:20:00-08:00']
612+
],
613+
[datetime.timedelta(seconds=40),
614+
['1997-01-01 00:00:00-08:00', '1997-01-01 00:00:05-08:00',
615+
'1997-01-01 00:00:10-08:00', '1997-01-01 00:00:15-08:00',
616+
'1997-01-01 00:00:20-08:00', '1997-01-01 00:00:25-08:00',
617+
'1997-01-01 00:00:30-08:00', '1997-01-01 00:00:35-08:00',
618+
'1997-01-01 00:00:40-08:00']
619+
]
620+
)
621+
622+
tz = dateutil.tz.gettz('Canada/Pacific')
623+
d1 = datetime.datetime(1997, 1, 1, tzinfo=tz)
624+
for t_delta, expected in results:
625+
with rc_context({'_internal.classic_mode': False}):
626+
d2 = d1 + t_delta
627+
locator = _create_auto_date_locator(d1, d2, tz)
628+
st = list(map(str, mdates.num2date(locator(), tz=tz)))
629+
assert st == expected
630+
631+
560632
@image_comparison(baseline_images=['date_inverted_limit'],
561633
extensions=['png'])
562634
def test_date_inverted_limit():
@@ -701,6 +773,30 @@ def attach_tz(dt, zi):
701773
_test_rrulewrapper(attach_tz, pytz.timezone)
702774

703775

776+
@pytest.mark.pytz
777+
@pytest.mark.skipif(not __has_pytz(), reason="Requires pytz")
778+
def test_yearlocator_pytz():
779+
import pytz
780+
781+
tz = pytz.timezone('America/New_York')
782+
x = [tz.localize(datetime.datetime(2010, 1, 1))
783+
+ datetime.timedelta(i) for i in range(2000)]
784+
locator = mdates.AutoDateLocator(interval_multiples=True, tz=tz)
785+
locator.create_dummy_axis()
786+
locator.set_view_interval(mdates.date2num(x[0])-1.0,
787+
mdates.date2num(x[-1])+1.0)
788+
789+
np.testing.assert_allclose([733408.208333, 733773.208333, 734138.208333,
790+
734503.208333, 734869.208333,
791+
735234.208333, 735599.208333], locator())
792+
expected = ['2009-01-01 00:00:00-05:00',
793+
'2010-01-01 00:00:00-05:00', '2011-01-01 00:00:00-05:00',
794+
'2012-01-01 00:00:00-05:00', '2013-01-01 00:00:00-05:00',
795+
'2014-01-01 00:00:00-05:00', '2015-01-01 00:00:00-05:00']
796+
st = list(map(str, mdates.num2date(locator(), tz=tz)))
797+
assert st == expected
798+
799+
704800
def test_DayLocator():
705801
with pytest.raises(ValueError):
706802
mdates.DayLocator(interval=-1)

0 commit comments

Comments
 (0)
0