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

Skip to content

Commit b208e4a

Browse files
committed
DateFormatter shows microseconds instead of %f for years <= 1900
Add a simple test for DateFormatter. closes #3179 Change-Id: Idff9d06cbc6dc00a3cb8dcf113983d82dbdd3fde
1 parent f529297 commit b208e4a

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

lib/matplotlib/dates.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -426,33 +426,35 @@ def _findall(self, text, substr):
426426
i = j + 1
427427
return sites
428428

429-
# Dalke: I hope I did this math right. Every 28 years the
430-
# calendar repeats, except through century leap years excepting
431-
# the 400 year leap years. But only if you're using the Gregorian
432-
# calendar.
433-
434429
def strftime(self, dt, fmt):
435430
fmt = self.illegal_s.sub(r"\1", fmt)
436431
fmt = fmt.replace("%s", "s")
437432
if dt.year > 1900:
438433
return cbook.unicode_safe(dt.strftime(fmt))
439434

435+
# Dalke: I hope I did this math right. Every 28 years the
436+
# calendar repeats, except through century leap years excepting
437+
# the 400 year leap years. But only if you're using the Gregorian
438+
# calendar.
439+
440440
year = dt.year
441441
# For every non-leap year century, advance by
442442
# 6 years to get into the 28-year repeat cycle
443443
delta = 2000 - year
444444
off = 6 * (delta // 100 + delta // 400)
445445
year = year + off
446446

447-
# Move to around the year 2000
447+
# Move to between the years 1973 and 2000
448448
year = year + ((2000 - year) // 28) * 28
449-
timetuple = dt.timetuple()
450-
s1 = time.strftime(fmt, (year,) + timetuple[1:])
449+
450+
s1 = dt.replace(year=year).strftime(fmt)
451451
sites1 = self._findall(s1, str(year))
452452

453-
s2 = time.strftime(fmt, (year + 28,) + timetuple[1:])
453+
s2 = dt.replace(year=year + 28).strftime(fmt)
454454
sites2 = self._findall(s2, str(year + 28))
455455

456+
# Generate timestamp string for year and year+28, and replace
457+
# instances of respective years in same location with dt's year
456458
sites = []
457459
for site in sites1:
458460
if site in sites2:

lib/matplotlib/tests/test_dates.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,39 @@ def test_DateFormatter():
158158
ax.autoscale_view()
159159
fig.autofmt_xdate()
160160

161+
def test_date_formatter_strftime():
162+
"""
163+
Tests that DateFormatter matches datetime.strftime,
164+
check microseconds for years before 1900 for bug #3179.
165+
"""
166+
def test_strftime_fields(dt):
167+
"""For datetime object dt, check DateFormatter fields"""
168+
formatter = mdates.DateFormatter("%d %m %Y %H %I %M %S %f")
169+
# Compute date fields without using datetime.strftime,
170+
# since datetime.strftime does not work before year 1900
171+
formatted_date_str = (
172+
"{day:02d} {month:02d} {full_year:4d} "
173+
"{hour24:02d} {hour12:02d} {minute:02d} {second:02d} "
174+
"{microsecond:06d}".format(
175+
# %w Sunday=0, weekday() Monday=0
176+
# Following do not work because of issue #3179
177+
# weekday = str((dt.weekday() + 1) % 7), # %w {weekday}
178+
# year = dt.year % 100, # %y {year:02d}
179+
# weeknum = dt.isocalendar()[1], # %U/%W {weeknum:02d}
180+
day = dt.day,
181+
month = dt.month,
182+
full_year = dt.year,
183+
hour24 = dt.hour,
184+
hour12 = ((dt.hour-1) % 12) + 1,
185+
minute = dt.minute,
186+
second = dt.second,
187+
microsecond = dt.microsecond))
188+
assert_equal(formatter.strftime(dt, formatter.fmt), formatted_date_str)
189+
190+
for year in range(1, 3000, 71):
191+
# Iterate through random set of years
192+
test_strftime_fields(datetime.datetime(year, 1, 1))
193+
test_strftime_fields(datetime.datetime(year, 2, 3, 4, 5, 6, 123456))
161194

162195
def test_date_formatter_callable():
163196
scale = -11

0 commit comments

Comments
 (0)