Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
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
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.22.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ Reshaping
Numeric
^^^^^^^

-
- Bug in :func:`Series.__sub__` subtracting a non-nanosecond ``np.datetime64`` object from a ``Series`` gave incorrect results (:issue:`7996`)
-
-

Expand Down
13 changes: 9 additions & 4 deletions pandas/core/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
is_datetimelike_v_numeric,
is_integer_dtype, is_categorical_dtype,
is_object_dtype, is_timedelta64_dtype,
is_datetime64_dtype, is_datetime64tz_dtype,
is_datetime64_dtype, is_datetime64tz_dtype, is_datetime64_ns_dtype,
is_bool_dtype, is_datetimetz,
is_list_like,
is_scalar,
Expand Down Expand Up @@ -497,6 +497,11 @@ def _convert_to_array(self, values, name=None, other=None):
elif not (isinstance(values, (np.ndarray, ABCSeries)) and
is_datetime64_dtype(values)):
values = libts.array_to_datetime(values)
elif (is_datetime64_dtype(values) and
not is_datetime64_ns_dtype(values)):
# GH#7996 e.g. np.datetime64('2013-01-01') is datetime64[D]
values = values.astype('datetime64[ns]')

elif inferred_type in ('timedelta', 'timedelta64'):
# have a timedelta, convert to to ns here
values = to_timedelta(values, errors='coerce', box=False)
Expand Down Expand Up @@ -671,7 +676,7 @@ def _arith_method_SERIES(op, name, str_rep, fill_zeros=None, default_axis=None,
"""
def na_op(x, y):
import pandas.core.computation.expressions as expressions

#
Copy link
Contributor

Choose a reason for hiding this comment

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

pls don't add extraneous things

try:
result = expressions.evaluate(op, str_rep, x, y, **eval_kwargs)
except TypeError:
Expand All @@ -688,9 +693,9 @@ def na_op(x, y):
raise TypeError("{typ} cannot perform the operation "
"{op}".format(typ=type(x).__name__,
op=str_rep))

#
result, changed = maybe_upcast_putmask(result, ~mask, np.nan)

#
result = missing.fill_zeros(result, x, y, name, fill_zeros)
return result

Expand Down
25 changes: 25 additions & 0 deletions pandas/tests/series/test_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,31 @@
from .common import TestData


class TestDatetimeLikeArithmetic(object):
def test_sub_datetime64_not_ns(self):
# GH#7996
Copy link
Contributor

Choose a reason for hiding this comment

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

parameterize this

ser = Series(date_range('20130101', periods=3))
dt64 = np.datetime64('2013-01-01')
Copy link
Contributor

Choose a reason for hiding this comment

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

test with a tz-aware as well (as I think that may hit your path, unless its getting caught earlier)

Copy link
Member Author

Choose a reason for hiding this comment

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

It gets caught earlier: tz compat raises ValueError in ops._validate

assert dt64.dtype == 'datetime64[D]'
res = ser - dt64
expected = pd.Series([Timedelta(days=0), Timedelta(days=1),
Timedelta(days=2)])
tm.assert_series_equal(res, expected)

res = dt64 - ser
tm.assert_series_equal(res, -expected)

# check for DatetimeIndex and DataFrame while we're at it
Copy link
Contributor

Choose a reason for hiding this comment

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

make the comment relevant

dti = pd.DatetimeIndex(ser)
res = dti - dt64
tm.assert_index_equal(res, pd.Index(expected))

res = dt64 - dti
tm.assert_index_equal(res, pd.Index(-expected))

# TODO: This is still broken for ser.to_frame()
Copy link
Contributor

Choose a reason for hiding this comment

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

then if you want to add a test with an xfail would be helpful. (and an issue reference), TODO's are only so good.



class TestSeriesOperators(TestData):

def test_series_comparison_scalars(self):
Expand Down