Skip to content

Commit 3f51046

Browse files
jbrockmendelyehoshuadimarsky
authored andcommitted
BUG: Timestamp with unit=Y or unit=M (pandas-dev#47266)
* BUG: Timestamp with unit=Y or unit=M * GH refs * remove unnecessary upper
1 parent 9bff442 commit 3f51046

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

doc/source/whatsnew/v1.5.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ Datetimelike
731731
- Bug in :meth:`SeriesGroupBy.value_counts` index when passing categorical column (:issue:`44324`)
732732
- Bug in :meth:`DatetimeIndex.tz_localize` localizing to UTC failing to make a copy of the underlying data (:issue:`46460`)
733733
- Bug in :meth:`DatetimeIndex.resolution` incorrectly returning "day" instead of "nanosecond" for nanosecond-resolution indexes (:issue:`46903`)
734+
- Bug in :class:`Timestamp` with an integer or float value and ``unit="Y"`` or ``unit="M"`` giving slightly-wrong results (:issue:`47266`)
734735
-
735736

736737
Timedelta

pandas/_libs/tslibs/conversion.pyx

+11-1
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit,
250250
if ts == NPY_NAT:
251251
obj.value = NPY_NAT
252252
else:
253+
if unit in ["Y", "M"]:
254+
# GH#47266 cast_from_unit leads to weird results e.g. with "Y"
255+
# and 150 we'd get 2120-01-01 09:00:00
256+
ts = np.datetime64(ts, unit)
257+
return convert_to_tsobject(ts, tz, None, False, False)
258+
253259
ts = ts * cast_from_unit(None, unit)
254260
obj.value = ts
255261
dt64_to_dtstruct(ts, &obj.dts)
@@ -258,7 +264,11 @@ cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit,
258264
obj.value = NPY_NAT
259265
else:
260266
if unit in ["Y", "M"]:
261-
if ts != int(ts):
267+
if ts == int(ts):
268+
# GH#47266 Avoid cast_from_unit, which would give weird results
269+
# e.g. with "Y" and 150.0 we'd get 2120-01-01 09:00:00
270+
return convert_to_tsobject(int(ts), tz, unit, False, False)
271+
else:
262272
# GH#47267 it is clear that 2 "M" corresponds to 1970-02-01,
263273
# but not clear what 2.5 "M" corresponds to, so we will
264274
# disallow that case.

pandas/tests/scalar/timestamp/test_constructors.py

+13
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@
2525

2626

2727
class TestTimestampConstructors:
28+
@pytest.mark.parametrize("typ", [int, float])
29+
def test_constructor_int_float_with_YM_unit(self, typ):
30+
# GH#47266 avoid the conversions in cast_from_unit
31+
val = typ(150)
32+
33+
ts = Timestamp(val, unit="Y")
34+
expected = Timestamp("2120-01-01")
35+
assert ts == expected
36+
37+
ts = Timestamp(val, unit="M")
38+
expected = Timestamp("1982-07-01")
39+
assert ts == expected
40+
2841
def test_constructor_float_not_round_with_YM_unit_deprecated(self):
2942
# GH#47267 avoid the conversions in cast_from-unit
3043

0 commit comments

Comments
 (0)