Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

FIX: translate timedeltas in _to_ordinalf #12863

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
48 changes: 38 additions & 10 deletions 48 lib/matplotlib/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ def _to_ordinalf(dt):
dt = dt.astimezone(UTC)
tzi = UTC

if isinstance(dt, datetime.timedelta):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this goes through, you need to update the docstring for _to_ordinalf to include timedelta.

base = dt / datetime.timedelta(days=1)
return base

base = float(dt.toordinal())

# If it's sufficiently datetime-like, it will have a `date()` method
Expand Down Expand Up @@ -251,6 +255,11 @@ def _dt64_to_ordinalf(d):
because we do times compared to ``0001-01-01T00:00:00`` (plus one day).
"""

if (isinstance(d, np.timedelta64) or
(isinstance(d, np.ndarray) and
np.issubdtype(d.dtype, np.timedelta64))):
return d / np.timedelta64(1, 'D')

# the "extra" ensures that we at least allow the dynamic range out to
# seconds. That should get out to +/-2e11 years.
# NOTE: First cast truncates; second cast back is for NumPy 1.10.
Expand All @@ -271,6 +280,11 @@ def _dt64_to_ordinalf(d):
return dt


def _dt64_to_ordinalf_iterable(d):
return np.fromiter((_dt64_to_ordinalf(dd) for dd in d),
float, count=len(d))


def _from_ordinalf(x, tz=None):
"""
Convert Gregorian float of the date, preserving hours, minutes,
Expand Down Expand Up @@ -405,22 +419,36 @@ def date2num(d):
Gregorian calendar is assumed; this is not universal practice.
For details see the module docstring.
"""

if hasattr(d, "values"):
# this unpacks pandas series or dataframes...
d = d.values
if not np.iterable(d):
if (isinstance(d, np.datetime64) or (isinstance(d, np.ndarray) and
np.issubdtype(d.dtype, np.datetime64))):
return _dt64_to_ordinalf(d)
return _to_ordinalf(d)

else:
d = np.asarray(d)
if np.issubdtype(d.dtype, np.datetime64):
if not np.iterable(d) and not isinstance(d, np.ndarray):
# single value logic...
if (isinstance(d, np.datetime64) or isinstance(d, np.timedelta64)):
return _dt64_to_ordinalf(d)
if not d.size:
return d
else:
return _to_ordinalf(d)

elif (isinstance(d, np.ndarray) and
(np.issubdtype(d.dtype, np.datetime64) or
np.issubdtype(d.dtype, np.timedelta64))):
# array with all one type of datetime64 object.
return _dt64_to_ordinalf(d)

elif len(d):
# this is a list or tuple...
if (isinstance(d[0], np.datetime64) or
isinstance(d[0], np.timedelta64)):
return _dt64_to_ordinalf_iterable(d)
return _to_ordinalf_np_vectorized(d)
elif hasattr(d, 'size') and not d.size:
# this elif doesn't get tested, but leaving here in case anyone
# needs it.
return d
else:
return []


def julian2num(j):
Expand Down
33 changes: 33 additions & 0 deletions 33 lib/matplotlib/tests/test_dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,3 +680,36 @@ def test_datetime64_in_list():
dt = [np.datetime64('2000-01-01'), np.datetime64('2001-01-01')]
dn = mdates.date2num(dt)
assert np.array_equal(dn, [730120., 730486.])


def test_timedelta():
"""
Test that timedelta objects are properly translated into days.
"""
dt = [datetime.datetime(2000, 1, 1, 0, 0, 0),
datetime.timedelta(days=1, hours=2)]
assert mdates.date2num(dt[1]) == 1 + 2 / 24
# check that mixed lists work....
assert mdates.date2num(dt)[0] == 730120.0
assert mdates.date2num(dt)[1] == 1 + 2 / 24

dt = (np.datetime64('2000-01-01'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line since a new part of the test starts here.

np.timedelta64(26, 'h'))
assert mdates.date2num(dt[1]) == 1 + 2 / 24
# check that mixed lists work....
assert mdates.date2num(dt)[0] == 730120.0
assert mdates.date2num(dt)[1] == 1 + 2 / 24

dt = [datetime.timedelta(days=1, hours=1),
datetime.timedelta(days=1, hours=2)]
assert mdates.date2num(dt)[0] == 1 + 1 / 24
assert mdates.date2num(dt)[1] == 1 + 2 / 24

dt = (np.timedelta64(25, 'h'),
np.timedelta64(26, 'h'))
assert mdates.date2num(dt)[0] == 1 + 1 / 24
assert mdates.date2num(dt)[1] == 1 + 2 / 24

dt = np.array([25, 26], dtype='timedelta64[h]')
assert mdates.date2num(dt)[0] == 1 + 1 / 24
assert mdates.date2num(dt)[1] == 1 + 2 / 24
Morty Proxy This is a proxified and sanitized view of the page, visit original site.