Skip to content

Commit

Permalink
Reduce AutoDateFormatter precision when possible
Browse files Browse the repository at this point in the history
Previously, the AutoDateFormatter would choose a format with second or
microsecond precision, even when the ticks were significantly coarser
than that. The resulting extra precision looks weird and can clutter the
display (especially with the long microsecond display).

This commit changes the default scale to format dictionary, which now
works as follows:

 - Use microsecond precision when the ticks are less than a second apart
 - Use second precision when the ticks are seconds apart
 - Use minute precision when the ticks are minutes or hours apart
 - Use day-precision, month or year precision when the ticks are days or more
   apart (unchanged).

Note that there is no point in displaying only the hour when the ticks are
hours apart, since then it won't be immediately clear that a time is being
displayed. Adding the (technically superfluous) :00 for the minutes should
make it immediately obvious that a time is being displayed, which is why the
minute precision should also be used when the ticks are hours apart.

While updating the documentation for this change, it was also changed to use
symbolic constants instead of hardcoded numbers. This should make it more clear
what the intention is.

Closes: matplotlib#4808
  • Loading branch information
matthijskooijman committed Jul 28, 2015
1 parent 465aecf commit 08b7821
Showing 1 changed file with 10 additions and 9 deletions.
19 changes: 10 additions & 9 deletions lib/matplotlib/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,13 +629,13 @@ class AutoDateFormatter(ticker.Formatter):
format string. The default looks like this::
self.scaled = {
365.0 : '%Y',
30. : '%b %Y',
1.0 : '%b %d %Y',
1./24. : '%H:%M:%S',
1. / (24. * 60.): '%H:%M:%S.%f',
}
DAYS_PER_YEAR : '%Y',
DAYS_PER_MONTH : '%b %Y',
1.0 : '%b %d %Y',
1. / HOURS_PER_DAY : '%H:%M',
1. / SEC_PER_DAY : '%H:%M:%S',
1. / MUSECONDS_PER_DAY : '%H:%M:%S.%f'
}
The algorithm picks the key in the dictionary that is >= the
current scale and uses that format string. You can customize this
Expand Down Expand Up @@ -688,8 +688,9 @@ def __init__(self, locator, tz=None, defaultfmt='%Y-%m-%d'):
self.scaled = {DAYS_PER_YEAR: '%Y',
DAYS_PER_MONTH: '%b %Y',
1.0: '%b %d %Y',
1. / HOURS_PER_DAY: '%H:%M:%S',
1. / (MINUTES_PER_DAY): '%H:%M:%S.%f'}
1. / HOURS_PER_DAY: '%H:%M',
1. / SEC_PER_DAY: '%H:%M:%S',
1. / MUSECONDS_PER_DAY: '%H:%M:%S.%f'}

def __call__(self, x, pos=None):
locator_unit_scale = float(self._locator._get_unit())
Expand Down

0 comments on commit 08b7821

Please sign in to comment.