Skip to content

Commit 512d214

Browse files
committed
Implement ConciseDateFormatter with format_ticks.
1 parent b715a34 commit 512d214

File tree

1 file changed

+66
-89
lines changed

1 file changed

+66
-89
lines changed

lib/matplotlib/dates.py

+66-89
Original file line numberDiff line numberDiff line change
@@ -820,8 +820,6 @@ def __init__(self, locator, tz=None, formats=None, offset_formats=None,
820820
"""
821821
self._locator = locator
822822
self._tz = tz
823-
self._oldticks = np.array([])
824-
self._oldlabels = None
825823
self.defaultfmt = '%Y'
826824
# there are 6 levels with each level getting a specific format
827825
# 0: mostly years, 1: months, 2: days,
@@ -869,95 +867,74 @@ def __init__(self, locator, tz=None, formats=None, offset_formats=None,
869867
'%Y-%b-%d',
870868
'%Y-%b-%d %H:%M']
871869
self.offset_string = ''
872-
self._formatter = DateFormatter(self.defaultfmt, self._tz)
873870
self.show_offset = show_offset
874871

875872
def __call__(self, x, pos=None):
876-
if hasattr(self._locator, '_get_unit'):
877-
locator_unit_scale = float(self._locator._get_unit())
878-
else:
879-
locator_unit_scale = 1.0
880-
ticks = self._locator()
881-
if pos is not None:
882-
if not np.array_equal(ticks, self._oldticks):
883-
884-
offset_fmt = ''
885-
fmt = self.defaultfmt
886-
self._formatter = DateFormatter(fmt, self._tz)
887-
tickdatetime = [num2date(tick) for tick in ticks]
888-
tickdate = np.array([tdt.timetuple()[:6]
889-
for tdt in tickdatetime])
890-
891-
# basic algorithm:
892-
# 1) only display a part of the date if it changes over the
893-
# ticks.
894-
# 2) don't display the smaller part of the date if:
895-
# it is always the same or if it is the start of the
896-
# year, month, day etc.
897-
# fmt for most ticks at this level
898-
fmts = self.formats
899-
# format beginnings of days, months, years, etc...
900-
zerofmts = self.zero_formats
901-
# offset fmt are for the offset in the upper left of the
902-
# or lower right of the axis.
903-
offsetfmts = self.offset_formats
904-
905-
# determine the level we will label at:
906-
# mostly 0: years, 1: months, 2: days,
907-
# 3: hours, 4: minutes, 5: seconds, 6: microseconds
908-
for level in range(5, -1, -1):
909-
if len(np.unique(tickdate[:, level])) > 1:
910-
break
911-
912-
# level is the basic level we will label at.
913-
# now loop through and decide the actual ticklabels
914-
zerovals = [0, 1, 1, 0, 0, 0, 0]
915-
ticknew = ['']*len(tickdate)
916-
for nn in range(len(tickdate)):
917-
if level < 5:
918-
if tickdate[nn][level] == zerovals[level]:
919-
fmt = zerofmts[level]
920-
else:
921-
fmt = fmts[level]
922-
else:
923-
# special handling for seconds + microseconds
924-
if (tickdatetime[nn].second == 0 and
925-
tickdatetime[nn].microsecond == 0):
926-
fmt = zerofmts[level]
927-
else:
928-
fmt = fmts[level]
929-
ticknew[nn] = tickdatetime[nn].strftime(fmt)
930-
931-
# special handling of seconds and microseconds:
932-
# strip extra zeros and decimal if possible...
933-
# this is complicated by two factors. 1) we have some
934-
# level-4 strings here (i.e. 03:00, '0.50000', '1.000')
935-
# 2) we would like to have the same number of decimals for
936-
# each string (i.e. 0.5 and 1.0).
937-
if level >= 5:
938-
trailing_zeros = min(
939-
(len(s) - len(s.rstrip('0')) for s in ticknew
940-
if '.' in s),
941-
default=None)
942-
if trailing_zeros:
943-
for nn in range(len(ticknew)):
944-
if '.' in ticknew[nn]:
945-
ticknew[nn] = \
946-
ticknew[nn][:-trailing_zeros].rstrip('.')
947-
948-
result = ticknew[pos]
949-
self._oldticks = ticks
950-
self._oldlabels = ticknew
951-
952-
# set the offset string:
953-
if self.show_offset:
954-
self.offset_string = tickdatetime[-1].strftime(
955-
offsetfmts[level])
956-
957-
result = self._oldlabels[pos]
958-
else:
959-
result = self._formatter(x, pos)
960-
return result
873+
formatter = DateFormatter(self.defaultfmt, self._tz)
874+
return formatter(x, pos=pos)
875+
876+
def format_ticks(self, values):
877+
tickdatetime = [num2date(value) for value in values]
878+
tickdate = np.array([tdt.timetuple()[:6] for tdt in tickdatetime])
879+
880+
# basic algorithm:
881+
# 1) only display a part of the date if it changes over the ticks.
882+
# 2) don't display the smaller part of the date if:
883+
# it is always the same or if it is the start of the
884+
# year, month, day etc.
885+
# fmt for most ticks at this level
886+
fmts = self.formats
887+
# format beginnings of days, months, years, etc...
888+
zerofmts = self.zero_formats
889+
# offset fmt are for the offset in the upper left of the
890+
# or lower right of the axis.
891+
offsetfmts = self.offset_formats
892+
893+
# determine the level we will label at:
894+
# mostly 0: years, 1: months, 2: days,
895+
# 3: hours, 4: minutes, 5: seconds, 6: microseconds
896+
for level in range(5, -1, -1):
897+
if len(np.unique(tickdate[:, level])) > 1:
898+
break
899+
900+
# level is the basic level we will label at.
901+
# now loop through and decide the actual ticklabels
902+
zerovals = [0, 1, 1, 0, 0, 0, 0]
903+
labels = [''] * len(tickdate)
904+
for nn in range(len(tickdate)):
905+
if level < 5:
906+
if tickdate[nn][level] == zerovals[level]:
907+
fmt = zerofmts[level]
908+
else:
909+
fmt = fmts[level]
910+
else:
911+
# special handling for seconds + microseconds
912+
if (tickdatetime[nn].second == tickdatetime[nn].microsecond
913+
== 0):
914+
fmt = zerofmts[level]
915+
else:
916+
fmt = fmts[level]
917+
labels[nn] = tickdatetime[nn].strftime(fmt)
918+
919+
# special handling of seconds and microseconds:
920+
# strip extra zeros and decimal if possible.
921+
# this is complicated by two factors. 1) we have some level-4 strings
922+
# here (i.e. 03:00, '0.50000', '1.000') 2) we would like to have the
923+
# same number of decimals for each string (i.e. 0.5 and 1.0).
924+
if level >= 5:
925+
trailing_zeros = min(
926+
(len(s) - len(s.rstrip('0')) for s in labels if '.' in s),
927+
default=None)
928+
if trailing_zeros:
929+
for nn in range(len(labels)):
930+
if '.' in labels[nn]:
931+
labels[nn] = labels[nn][:-trailing_zeros].rstrip('.')
932+
933+
if self.show_offset:
934+
# set the offset string:
935+
self.offset_string = tickdatetime[-1].strftime(offsetfmts[level])
936+
937+
return labels
961938

962939
def get_offset(self):
963940
return self.offset_string
@@ -2064,7 +2041,7 @@ class ConciseDateConverter(DateConverter):
20642041
"""
20652042

20662043
def __init__(self, formats=None, zero_formats=None, offset_formats=None,
2067-
show_offset=True):
2044+
show_offset=True):
20682045
self._formats = formats
20692046
self._zero_formats = zero_formats
20702047
self._offset_formats = offset_formats

0 commit comments

Comments
 (0)