diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index d24c595cacab5..5ab183ed81740 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -335,6 +335,7 @@ Indexing - Bug in :meth:`DataFrame.__getitem__` and :meth:`Series.__getitem__` always raising ``KeyError`` when slicing with existing strings an :class:`Index` with milliseconds (:issue:`33589`) - Bug in setting ``timedelta64`` values into numeric :class:`Series` failing to cast to object dtype (:issue:`39086`) - Bug in setting :class:`Interval` values into a :class:`Series` or :class:`DataFrame` with mismatched :class:`IntervalDtype` incorrectly casting the new values to the existing dtype (:issue:`39120`) +- Bug in setting ``datetime64`` values into a :class:`Series` with integer-dtype incorrect casting the datetime64 values to integers (:issue:`39266`) - Bug in incorrectly raising in :meth:`Index.insert`, when setting a new column that cannot be held in the existing ``frame.columns``, or in :meth:`Series.reset_index` or :meth:`DataFrame.reset_index` instead of casting to a compatible dtype (:issue:`39068`) Missing diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index fe5256ca42982..eb8bb0fe90e9a 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -968,8 +968,18 @@ def setitem(self, indexer, value): # TODO(EA2D): special case not needed with 2D EA values[indexer] = value.to_numpy(values.dtype).reshape(-1, 1) - # set + elif self.is_object and not is_ea_value and arr_value.dtype.kind in ["m", "M"]: + # https://github.com/numpy/numpy/issues/12550 + # numpy will incorrect cast to int if we're not careful + if is_list_like(value): + value = list(value) + else: + value = [value] * len(values[indexer]) + + values[indexer] = value + else: + values[indexer] = value if transpose: diff --git a/pandas/tests/series/indexing/test_setitem.py b/pandas/tests/series/indexing/test_setitem.py index 06a1beffc3a68..f08b1511c455c 100644 --- a/pandas/tests/series/indexing/test_setitem.py +++ b/pandas/tests/series/indexing/test_setitem.py @@ -257,6 +257,27 @@ def test_setitem_callable_other(self): tm.assert_series_equal(ser, expected) +class TestSetitemCasting: + @pytest.mark.parametrize("dtype", ["M8[ns]", "m8[ns]"]) + def test_setitem_dt64_into_int_series(self, dtype): + # dont cast dt64 to int when doing this setitem + orig = Series([1, 2, 3]) + + val = np.datetime64("2021-01-18 13:25:00", "ns") + if dtype == "m8[ns]": + val = val - val + + ser = orig.copy() + ser[:-1] = val + expected = Series([val, val, 3], dtype=object) + tm.assert_series_equal(ser, expected) + assert isinstance(ser[0], type(val)) + + ser = orig.copy() + ser[:-1] = np.array([val, val]) + tm.assert_series_equal(ser, expected) + + @pytest.mark.parametrize( "obj,expected,key", [