Skip to content

Commit 61ace78

Browse files
committed
Merge branch 'main' into bug-normalize
2 parents 8c264b3 + 29ce489 commit 61ace78

File tree

4 files changed

+26
-6
lines changed

4 files changed

+26
-6
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,7 @@ Datetimelike
903903
- Bug in :meth:`Index.union` with a ``pyarrow`` timestamp dtype incorrectly returning ``object`` dtype (:issue:`58421`)
904904
- Bug in :meth:`Series.dt.microsecond` producing incorrect results for pyarrow backed :class:`Series`. (:issue:`59154`)
905905
- Bug in :meth:`Timestamp.normalize` and :meth:`DatetimeArray.normalize` returning incorrect results instead of raising on integer overflow for very small (distant past) values (:issue:`60583`)
906+
- Bug in :meth:`Timestamp.replace` failing to update ``unit`` attribute when replacement introduces non-zero ``nanosecond`` or ``microsecond`` (:issue:`57749`)
906907
- Bug in :meth:`to_datetime` not respecting dayfirst if an uncommon date string was passed. (:issue:`58859`)
907908
- Bug in :meth:`to_datetime` on float array with missing values throwing ``FloatingPointError`` (:issue:`58419`)
908909
- Bug in :meth:`to_datetime` on float32 df with year, month, day etc. columns leads to precision issues and incorrect result. (:issue:`60506`)

pandas/_libs/tslibs/timestamps.pyx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3362,6 +3362,7 @@ default 'raise'
33623362
datetime ts_input
33633363
tzinfo_type tzobj
33643364
_TSObject ts
3365+
NPY_DATETIMEUNIT creso = self._creso
33653366
33663367
# set to naive if needed
33673368
tzobj = self.tzinfo
@@ -3401,8 +3402,12 @@ default 'raise'
34013402
dts.sec = validate("second", second)
34023403
if microsecond is not None:
34033404
dts.us = validate("microsecond", microsecond)
3405+
if creso < NPY_DATETIMEUNIT.NPY_FR_us:
3406+
# GH#57749
3407+
creso = NPY_DATETIMEUNIT.NPY_FR_us
34043408
if nanosecond is not None:
34053409
dts.ps = validate("nanosecond", nanosecond) * 1000
3410+
creso = NPY_FR_ns # GH#57749
34063411
if tzinfo is not object:
34073412
tzobj = tzinfo
34083413
@@ -3412,17 +3417,17 @@ default 'raise'
34123417
# to datetimes outside of pydatetime range.
34133418
ts = _TSObject()
34143419
try:
3415-
ts.value = npy_datetimestruct_to_datetime(self._creso, &dts)
3420+
ts.value = npy_datetimestruct_to_datetime(creso, &dts)
34163421
except OverflowError as err:
34173422
fmt = dts_to_iso_string(&dts)
34183423
raise OutOfBoundsDatetime(
34193424
f"Out of bounds timestamp: {fmt} with frequency '{self.unit}'"
34203425
) from err
34213426
ts.dts = dts
3422-
ts.creso = self._creso
3427+
ts.creso = creso
34233428
ts.fold = fold
34243429
return create_timestamp_from_ts(
3425-
ts.value, dts, tzobj, fold, reso=self._creso
3430+
ts.value, dts, tzobj, fold, reso=creso
34263431
)
34273432
34283433
elif tzobj is not None and treat_tz_as_pytz(tzobj):
@@ -3441,10 +3446,10 @@ default 'raise'
34413446
ts_input = datetime(**kwargs)
34423447
34433448
ts = convert_datetime_to_tsobject(
3444-
ts_input, tzobj, nanos=dts.ps // 1000, reso=self._creso
3449+
ts_input, tzobj, nanos=dts.ps // 1000, reso=creso
34453450
)
34463451
return create_timestamp_from_ts(
3447-
ts.value, dts, tzobj, fold, reso=self._creso
3452+
ts.value, dts, tzobj, fold, reso=creso
34483453
)
34493454
34503455
def to_julian_date(self) -> np.float64:

pandas/tests/reshape/test_pivot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ def test_pivot_tz_in_values(self):
642642
)
643643

644644
df = df.set_index("ts").reset_index()
645-
mins = df.ts.map(lambda x: x.replace(hour=0, minute=0, second=0, microsecond=0))
645+
mins = df.ts.map(lambda x: x.replace(hour=0, minute=0, second=0))
646646

647647
result = pivot_table(
648648
df.set_index("ts").reset_index(),

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,17 @@ def test_replace_preserves_fold(self, fold):
195195
ts_replaced = ts.replace(second=1)
196196

197197
assert ts_replaced.fold == fold
198+
199+
def test_replace_updates_unit(self):
200+
# GH#57749
201+
ts = Timestamp("2023-07-15 23:08:12.134567123")
202+
ts2 = Timestamp("2023-07-15 23:08:12.000000")
203+
assert ts2.unit == "us"
204+
result = ts2.replace(microsecond=ts.microsecond, nanosecond=ts.nanosecond)
205+
assert result.unit == "ns"
206+
assert result == ts
207+
208+
ts3 = Timestamp("2023-07-15 23:08:12").as_unit("s")
209+
result = ts3.replace(microsecond=ts2.microsecond)
210+
assert result.unit == "us"
211+
assert result == ts2

0 commit comments

Comments
 (0)