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

Skip to content

improve sub-second datetime plotting and documentation #10076

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jan 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
140b766
dates: fix guaranteed typo
nmartensen Dec 22, 2017
9902349
doc: AutoDateLocator does not always pick RRuleLocator
nmartensen Dec 22, 2017
6107cf3
doc: MicrosecondLocator: Add note on limitations and workaround
nmartensen Dec 22, 2017
3ab1193
dates._from_ordinalf: Use normal rounding for microseconds
nmartensen Dec 22, 2017
0e79f69
dates: add parameter for microsecond precision
nmartensen Dec 23, 2017
1c40269
dates: select microsecond precision in AutoDateFormatter
nmartensen Dec 23, 2017
bc92319
dates: remove "bad plot" warning from docstring note
nmartensen Dec 23, 2017
74d354d
dates: add warning for usec precision with high years
nmartensen Dec 23, 2017
59f7f52
dates: adjust view/datalim for longer plots
nmartensen Dec 26, 2017
7a74530
dates: coerce to int
nmartensen Dec 26, 2017
3f3dfcf
test_dates: update test_auto_date_locator* expected results
nmartensen Dec 26, 2017
63b9849
test_axes: update expected result images
nmartensen Dec 27, 2017
c419583
test_dates: update DateFormatter expected result image
nmartensen Dec 27, 2017
d67333e
dates/microsecondlocator: refine warning
nmartensen Jan 7, 2018
06b65a8
dates: remove musec_prec parameter again
nmartensen Jan 7, 2018
3dd0800
doc: dates: update microsecondlocator note
nmartensen Jan 7, 2018
6fb7c12
Revert "test_axes: update expected result images"
nmartensen Jan 7, 2018
e04464a
test_dates: update fractional seconds result image
nmartensen Jan 7, 2018
4a4c216
dates: use _log.warn for sub-second warning
nmartensen Jan 7, 2018
45ff942
dates: address review comments
nmartensen Jan 8, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 41 additions & 10 deletions lib/matplotlib/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,12 @@
<../gallery/ticks_and_spines/date_demo_rrule.html>`_.

* :class:`AutoDateLocator`: On autoscale, this class picks the best
:class:`RRuleLocator` to set the view limits and the tick
:class:`DateLocator` (e.g., :class:`RRuleLocator`)
to set the view limits and the tick
locations. If called with ``interval_multiples=True`` it will
make ticks line up with sensible multiples of the tick intervals. E.g.
if the interval is 4 hours, it will pick hours 0, 4, 8, etc as ticks.
This behaviour is not garaunteed by default.
This behaviour is not guaranteed by default.

Date formatters
---------------
Expand Down Expand Up @@ -128,6 +129,7 @@
import functools

import warnings
import logging


from dateutil.rrule import (rrule, MO, TU, WE, TH, FR, SA, SU, YEARLY,
Expand Down Expand Up @@ -157,6 +159,9 @@
'seconds', 'minutes', 'hours', 'weeks')


_log = logging.getLogger(__name__)


# Make a simple UTC instance so we don't always have to import
# pytz. From the python datetime library docs:

Expand Down Expand Up @@ -286,14 +291,21 @@ def _from_ordinalf(x, tz=None):

remainder = float(x) - ix

# Round down to the nearest microsecond.
dt += datetime.timedelta(microseconds=int(remainder * MUSECONDS_PER_DAY))
# Since the input date `x` float is unable to preserve microsecond
# precision of time representation in non-antique years, the
# resulting datetime is rounded to the nearest multiple of
# `musec_prec`. A value of 20 is appropriate for current dates.
musec_prec = 20
remainder_musec = int(round(remainder * MUSECONDS_PER_DAY /
float(musec_prec)) * musec_prec)

# Compensate for rounding errors
if dt.microsecond < 10:
dt = dt.replace(microsecond=0)
elif dt.microsecond > 999990:
dt += datetime.timedelta(microseconds=1e6 - dt.microsecond)
# For people trying to plot with full microsecond precision, enable
# an early-year workaround
if x < 30 * 365:
remainder_musec = int(round(remainder * MUSECONDS_PER_DAY))

# add hours, minutes, seconds, microseconds
dt += datetime.timedelta(microseconds=remainder_musec)

return dt.astimezone(tz)

Expand Down Expand Up @@ -1296,6 +1308,11 @@ def get_locator(self, dmin, dmax):
locator = RRuleLocator(rrule, self.tz)
else:
locator = MicrosecondLocator(interval, tz=self.tz)
if dmin.year > 20 and interval < 1000:
_log.warn('Plotting microsecond time intervals is not'
' well supported. Please see the'
' MicrosecondLocator documentation'
' for details.')

locator.set_axis(self.axis)

Expand Down Expand Up @@ -1511,7 +1528,21 @@ def __init__(self, bysecond=None, interval=1, tz=None):

class MicrosecondLocator(DateLocator):
"""
Make ticks on occurances of each microsecond.
Make ticks on regular intervals of one or more microsecond(s).

.. note::

Due to the floating point representation of time in days since
0001-01-01 UTC (plus 1), plotting data with microsecond time
resolution does not work well with current dates.

If you want microsecond resolution time plots, it is strongly
recommended to use floating point seconds, not datetime-like
time representation.

If you really must use datetime.datetime() or similar and still
need microsecond precision, your only chance is to use very
early years; using year 0001 is recommended.

"""
def __init__(self, interval=1, tz=None):
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 8 additions & 9 deletions lib/matplotlib/tests/test_dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,6 @@ def _create_auto_date_locator(date1, date2):
['1990-01-01 00:00:00+00:00', '1990-01-01 00:05:00+00:00',
'1990-01-01 00:10:00+00:00', '1990-01-01 00:15:00+00:00',
'1990-01-01 00:20:00+00:00']

],
[datetime.timedelta(seconds=40),
['1990-01-01 00:00:00+00:00', '1990-01-01 00:00:05+00:00',
Expand All @@ -365,11 +364,11 @@ def _create_auto_date_locator(date1, date2):
'1990-01-01 00:00:40+00:00']
],
[datetime.timedelta(microseconds=1500),
['1989-12-31 23:59:59.999507+00:00',
['1989-12-31 23:59:59.999500+00:00',
'1990-01-01 00:00:00+00:00',
'1990-01-01 00:00:00.000502+00:00',
'1990-01-01 00:00:00.001005+00:00',
'1990-01-01 00:00:00.001508+00:00']
'1990-01-01 00:00:00.000500+00:00',
'1990-01-01 00:00:00.001000+00:00',
'1990-01-01 00:00:00.001500+00:00']
],
)

Expand Down Expand Up @@ -438,11 +437,11 @@ def _create_auto_date_locator(date1, date2):
'1997-01-01 00:00:40+00:00']
],
[datetime.timedelta(microseconds=1500),
['1996-12-31 23:59:59.999507+00:00',
['1996-12-31 23:59:59.999500+00:00',
'1997-01-01 00:00:00+00:00',
'1997-01-01 00:00:00.000502+00:00',
'1997-01-01 00:00:00.001005+00:00',
'1997-01-01 00:00:00.001508+00:00']
'1997-01-01 00:00:00.000500+00:00',
'1997-01-01 00:00:00.001000+00:00',
'1997-01-01 00:00:00.001500+00:00']
],
)

Expand Down