Skip to content

Commit a75f375

Browse files
committed
core: try coerce result back to DatetimeBlock
1 parent 37c7458 commit a75f375

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

doc/source/whatsnew/v0.24.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ Datetimelike
436436

437437
- Fixed bug where two :class:`DateOffset` objects with different ``normalize`` attributes could evaluate as equal (:issue:`21404`)
438438
- Fixed bug where :meth:`Timestamp.resolution` incorrectly returned 1-microsecond ``timedelta`` instead of 1-nanosecond :class:`Timedelta` (:issue:`21336`,:issue:`21365`)
439+
- Fixed bug where :class:`DataFrame` with ``dtype='datetime64[ns]'`` operating with :class:`DateOffset` could cast to ``dtype='object'`` (:issue:`21610`)
439440

440441
Timedelta
441442
^^^^^^^^^

pandas/core/internals/__init__.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -2737,7 +2737,7 @@ def _try_coerce_args(self, values, other):
27372737

27382738
def _try_coerce_result(self, result):
27392739
""" reverse of try_coerce_args """
2740-
if isinstance(result, np.ndarray):
2740+
if isinstance(result, (np.ndarray, Block)):
27412741
if result.dtype.kind in ['i', 'f', 'O']:
27422742
try:
27432743
result = result.astype('M8[ns]')
@@ -2785,6 +2785,12 @@ def set(self, locs, values, check=False):
27852785

27862786
self.values[locs] = values
27872787

2788+
def eval(self, try_cast=False, *args, **kwargs):
2789+
blocks = super().eval(try_cast=try_cast, *args, **kwargs)
2790+
if try_cast:
2791+
blocks = [self._try_coerce_result(block) for block in blocks]
2792+
return blocks
2793+
27882794

27892795
class DatetimeTZBlock(NonConsolidatableMixIn, DatetimeBlock):
27902796
""" implement a datetime64 block with a tz attribute """
@@ -2920,6 +2926,8 @@ def _try_coerce_result(self, result):
29202926
if isinstance(result, np.ndarray):
29212927
if result.dtype.kind in ['i', 'f', 'O']:
29222928
result = result.astype('M8[ns]')
2929+
elif isinstance(result, Block):
2930+
result = self.make_block_same_class(result.values.flat)
29232931
elif isinstance(result, (np.integer, np.float, np.datetime64)):
29242932
result = tslibs.Timestamp(result, tz=self.values.tz)
29252933
if isinstance(result, np.ndarray):

pandas/tests/frame/test_arithmetic.py

+10
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,16 @@ def test_df_sub_datetime64_not_ns(self):
211211
pd.Timedelta(days=2)])
212212
tm.assert_frame_equal(res, expected)
213213

214+
def test_timestamp_df_add_dateoffset(self):
215+
expected = pd.DataFrame([pd.Timestamp('2019')])
216+
result = pd.DataFrame([pd.Timestamp('2018')]) + pd.DateOffset(years=1)
217+
tm.assert_frame_equal(expected, result)
218+
219+
expected = pd.DataFrame([pd.Timestamp('2019', tz='Asia/Shanghai')])
220+
result = (pd.DataFrame([pd.Timestamp('2018', tz='Asia/Shanghai')])
221+
+ pd.DateOffset(years=1))
222+
tm.assert_frame_equal(expected, result)
223+
214224
@pytest.mark.parametrize('data', [
215225
[1, 2, 3],
216226
[1.1, 2.2, 3.3],

0 commit comments

Comments
 (0)