Skip to content

Commit 5e6c223

Browse files
BUG: Fix bug where when replaced with 0 it Timestamp.replace didn't recalculate precision
1 parent f0c77d3 commit 5e6c223

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

doc/source/whatsnew/v3.0.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,6 @@ Performance improvements
473473

474474
Bug fixes
475475
~~~~~~~~~
476-
- Fixed bug in :meth:`Timestamp.replace` where it would not reflect changes into :meth:`Timestamp.unit`. (:issue:`57749`)
477476

478477
Categorical
479478
^^^^^^^^^^^
@@ -491,6 +490,7 @@ Datetimelike
491490
- Bug in :meth:`DatetimeIndex.is_year_start` and :meth:`DatetimeIndex.is_quarter_start` does not raise on Custom business days frequencies bigger then "1C" (:issue:`58664`)
492491
- Bug in :meth:`DatetimeIndex.is_year_start` and :meth:`DatetimeIndex.is_quarter_start` returning ``False`` on double-digit frequencies (:issue:`58523`)
493492
- Bug in setting scalar values with mismatched resolution into arrays with non-nanosecond ``datetime64``, ``timedelta64`` or :class:`DatetimeTZDtype` incorrectly truncating those scalars (:issue:`56410`)
493+
- Bug in :meth:`Timestamp.replace` where it would not reflect changes into :meth:`Timestamp.unit`. (:issue:`57749`)
494494

495495
Timedelta
496496
^^^^^^^^^

pandas/_libs/tslibs/timestamps.pyx

+16-1
Original file line numberDiff line numberDiff line change
@@ -2633,6 +2633,8 @@ default 'raise'
26332633
pandas_datetime_to_datetimestruct(value, self._creso, &dts)
26342634
dts.ps = self.nanosecond * 1000
26352635

2636+
zero_set = False
2637+
26362638
# replace
26372639
def validate(k, v):
26382640
""" validate integers """
@@ -2666,13 +2668,26 @@ default 'raise'
26662668
rep_reso = NPY_DATETIMEUNIT.NPY_FR_us
26672669
else:
26682670
rep_reso = NPY_DATETIMEUNIT.NPY_FR_ms
2671+
if microsecond == 0:
2672+
zero_set = True
26692673
if nanosecond is not None:
26702674
dts.ps = validate("nanosecond", nanosecond) * 1000
26712675
rep_reso = NPY_DATETIMEUNIT.NPY_FR_ns
2676+
if nanosecond == 0:
2677+
zero_set = True
26722678
if tzinfo is not object:
26732679
tzobj = tzinfo
26742680

2675-
if rep_reso < self._creso:
2681+
# Recalculate the replacement resolution if a unit was replaced with 0
2682+
if zero_set:
2683+
if dts.ps != 0:
2684+
rep_reso = NPY_DATETIMEUNIT.NPY_FR_ns
2685+
elif dts.us != 0:
2686+
rep_reso = NPY_DATETIMEUNIT.NPY_FR_us
2687+
else:
2688+
rep_reso = NPY_DATETIMEUNIT.NPY_FR_s
2689+
2690+
if rep_reso < self._creso and not zero_set:
26762691
rep_reso = self._creso
26772692

26782693
# reconstruct & check bounds

pandas/tests/scalar/timestamp/methods/test_replace.py

+6
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,9 @@ def test_replace_unit(self):
206206
ts = ts.replace(nanosecond=ts2.nanosecond)
207207
assert ts.unit == "ns"
208208
assert ts == ts2
209+
210+
def test_replace_resets_to_more_precise(self):
211+
# GH#57749
212+
ts = Timestamp(year=2020, month=1, day=1, nanosecond=5)
213+
result = ts.replace(nanosecond=0)
214+
assert result.unit == "s"

0 commit comments

Comments
 (0)