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

Skip to content

Commit 34cd842

Browse files
committed
FIX: properly set tz for YearLocator
FIX: add check for py3.5 to fail if naive datetime
1 parent 9e8be5b commit 34cd842

File tree

2 files changed

+94
-6
lines changed

2 files changed

+94
-6
lines changed

lib/matplotlib/dates.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,7 +1189,7 @@ def __init__(self, tz=None, minticks=5, maxticks=None,
11891189
locator.intervald[HOURLY] = [3] # only show every 3 hours
11901190
"""
11911191
DateLocator.__init__(self, tz)
1192-
self._locator = YearLocator()
1192+
self._locator = YearLocator(tz=tz)
11931193
self._freq = YEARLY
11941194
self._freqs = [YEARLY, MONTHLY, DAILY, HOURLY, MINUTELY,
11951195
SECONDLY, MICROSECONDLY]
@@ -1344,7 +1344,7 @@ def get_locator(self, dmin, dmax):
13441344
'AutoDateLocator.')
13451345

13461346
if (freq == YEARLY) and self.interval_multiples:
1347-
locator = YearLocator(interval)
1347+
locator = YearLocator(interval, tz=self.tz)
13481348
elif use_rrule_locator[i]:
13491349
_, bymonth, bymonthday, byhour, byminute, bysecond, _ = byranges
13501350
rrule = rrulewrapper(self._freq, interval=interval,
@@ -1393,8 +1393,10 @@ def __init__(self, base=1, month=1, day=1, tz=None):
13931393
'hour': 0,
13941394
'minute': 0,
13951395
'second': 0,
1396-
'tzinfo': tz
13971396
}
1397+
# Note that tzinfo does not work with pytz timezones, and
1398+
# astimezone doesn't work unless a datetime has timezone info (for
1399+
# py3.5). So the user should provide time-zone aware dates.
13981400

13991401
def __call__(self):
14001402
# if no data have been set, this will tank with a ValueError
@@ -1409,13 +1411,21 @@ def tick_values(self, vmin, vmax):
14091411
ymin = self.base.le(vmin.year) * self.base.step
14101412
ymax = self.base.ge(vmax.year) * self.base.step
14111413

1412-
ticks = [vmin.replace(year=ymin, **self.replaced)]
1414+
vmin = vmin.replace(year=ymin, **self.replaced)
1415+
try:
1416+
ticks = [vmin.astimezone(self.tz)]
1417+
except ValueError:
1418+
raise ValueError('naive datetime objects cannot be used '
1419+
'with matplotlib for python < 3.6; '
1420+
'astimezone() cannot '
1421+
'be applied to a naive datetime.')
14131422
while True:
14141423
dt = ticks[-1]
14151424
if dt.year >= ymax:
14161425
return date2num(ticks)
14171426
year = dt.year + self.base.step
1418-
ticks.append(dt.replace(year=year, **self.replaced))
1427+
dt = dt.replace(year=year, **self.replaced).astimezone(self.tz)
1428+
ticks.append(dt)
14191429

14201430
def autoscale(self):
14211431
"""
@@ -1426,7 +1436,9 @@ def autoscale(self):
14261436
ymin = self.base.le(dmin.year)
14271437
ymax = self.base.ge(dmax.year)
14281438
vmin = dmin.replace(year=ymin, **self.replaced)
1439+
vmin = vmin.astimezone(self.tz)
14291440
vmax = dmax.replace(year=ymax, **self.replaced)
1441+
vmax = vmax.astimezone(self.tz)
14301442

14311443
vmin = date2num(vmin)
14321444
vmax = date2num(vmax)

lib/matplotlib/tests/test_dates.py

Lines changed: 77 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,12 +500,88 @@ 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)
506507
assert list(map(str, mdates.num2date(locator()))) == expected
507508

508509

510+
@pytest.mark.pytz
511+
@pytest.mark.skipif(not __has_pytz(), reason="Requires pytz")
512+
def test_auto_date_locator_intmult_tz():
513+
import pytz
514+
515+
def _create_auto_date_locator(date1, date2, tz):
516+
locator = mdates.AutoDateLocator(interval_multiples=True, tz=tz)
517+
locator.create_dummy_axis()
518+
locator.set_view_interval(mdates.date2num(date1),
519+
mdates.date2num(date2))
520+
return locator
521+
522+
results = ([datetime.timedelta(weeks=52*200),
523+
['1980-01-01 00:00:00-08:00', '2000-01-01 00:00:00-08:00',
524+
'2020-01-01 00:00:00-08:00', '2040-01-01 00:00:00-08:00',
525+
'2060-01-01 00:00:00-08:00', '2080-01-01 00:00:00-08:00',
526+
'2100-01-01 00:00:00-08:00', '2120-01-01 00:00:00-08:00',
527+
'2140-01-01 00:00:00-08:00', '2160-01-01 00:00:00-08:00',
528+
'2180-01-01 00:00:00-08:00', '2200-01-01 00:00:00-08:00']
529+
],
530+
[datetime.timedelta(weeks=52),
531+
['1997-01-01 00:00:00-08:00', '1997-02-01 00:00:00-08:00',
532+
'1997-03-01 00:00:00-08:00', '1997-04-01 00:00:00-08:00',
533+
'1997-05-01 00:00:00-07:00', '1997-06-01 00:00:00-07:00',
534+
'1997-07-01 00:00:00-07:00', '1997-08-01 00:00:00-07:00',
535+
'1997-09-01 00:00:00-07:00', '1997-10-01 00:00:00-07:00',
536+
'1997-11-01 00:00:00-08:00', '1997-12-01 00:00:00-08:00']
537+
],
538+
[datetime.timedelta(days=141),
539+
['1997-01-01 00:00:00-08:00', '1997-01-22 00:00:00-08:00',
540+
'1997-02-01 00:00:00-08:00', '1997-02-22 00:00:00-08:00',
541+
'1997-03-01 00:00:00-08:00', '1997-03-22 00:00:00-08:00',
542+
'1997-04-01 00:00:00-08:00', '1997-04-22 00:00:00-07:00',
543+
'1997-05-01 00:00:00-07:00', '1997-05-22 00:00:00-07:00']
544+
],
545+
[datetime.timedelta(days=40),
546+
['1997-01-01 00:00:00-08:00', '1997-01-05 00:00:00-08:00',
547+
'1997-01-09 00:00:00-08:00', '1997-01-13 00:00:00-08:00',
548+
'1997-01-17 00:00:00-08:00', '1997-01-21 00:00:00-08:00',
549+
'1997-01-25 00:00:00-08:00', '1997-01-29 00:00:00-08:00',
550+
'1997-02-01 00:00:00-08:00', '1997-02-05 00:00:00-08:00',
551+
'1997-02-09 00:00:00-08:00']
552+
],
553+
[datetime.timedelta(hours=40),
554+
['1997-01-01 00:00:00-08:00', '1997-01-01 04:00:00-08:00',
555+
'1997-01-01 08:00:00-08:00', '1997-01-01 12:00:00-08:00',
556+
'1997-01-01 16:00:00-08:00', '1997-01-01 20:00:00-08:00',
557+
'1997-01-02 00:00:00-08:00', '1997-01-02 04:00:00-08:00',
558+
'1997-01-02 08:00:00-08:00', '1997-01-02 12:00:00-08:00',
559+
'1997-01-02 16:00:00-08:00']
560+
],
561+
[datetime.timedelta(minutes=20),
562+
['1997-01-01 00:00:00-08:00', '1997-01-01 00:05:00-08:00',
563+
'1997-01-01 00:10:00-08:00', '1997-01-01 00:15:00-08:00',
564+
'1997-01-01 00:20:00-08:00']
565+
],
566+
[datetime.timedelta(seconds=40),
567+
['1997-01-01 00:00:00-08:00', '1997-01-01 00:00:05-08:00',
568+
'1997-01-01 00:00:10-08:00', '1997-01-01 00:00:15-08:00',
569+
'1997-01-01 00:00:20-08:00', '1997-01-01 00:00:25-08:00',
570+
'1997-01-01 00:00:30-08:00', '1997-01-01 00:00:35-08:00',
571+
'1997-01-01 00:00:40-08:00']
572+
]
573+
)
574+
575+
tz = pytz.timezone('US/Pacific')
576+
d1 = tz.localize(datetime.datetime(1997, 1, 1))
577+
for t_delta, expected in results:
578+
with rc_context({'_internal.classic_mode': False}):
579+
d2 = d1 + t_delta
580+
locator = _create_auto_date_locator(d1, d2, tz)
581+
st = list(map(str, mdates.num2date(locator(), tz=tz)))
582+
assert st == expected
583+
584+
509585
@image_comparison(baseline_images=['date_inverted_limit'],
510586
extensions=['png'])
511587
def test_date_inverted_limit():

0 commit comments

Comments
 (0)