Skip to content

Commit

Permalink
BUG: Timestamp with unit=Y or unit=M (pandas-dev#47266)
Browse files Browse the repository at this point in the history
* BUG: Timestamp with unit=Y or unit=M

* GH refs

* remove unnecessary upper
  • Loading branch information
jbrockmendel authored and yehoshuadimarsky committed Jul 13, 2022
1 parent 9bff442 commit 3f51046
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 1 deletion.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ Datetimelike
- Bug in :meth:`SeriesGroupBy.value_counts` index when passing categorical column (:issue:`44324`)
- Bug in :meth:`DatetimeIndex.tz_localize` localizing to UTC failing to make a copy of the underlying data (:issue:`46460`)
- Bug in :meth:`DatetimeIndex.resolution` incorrectly returning "day" instead of "nanosecond" for nanosecond-resolution indexes (:issue:`46903`)
- Bug in :class:`Timestamp` with an integer or float value and ``unit="Y"`` or ``unit="M"`` giving slightly-wrong results (:issue:`47266`)
-

Timedelta
Expand Down
12 changes: 11 additions & 1 deletion pandas/_libs/tslibs/conversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit,
if ts == NPY_NAT:
obj.value = NPY_NAT
else:
if unit in ["Y", "M"]:
# GH#47266 cast_from_unit leads to weird results e.g. with "Y"
# and 150 we'd get 2120-01-01 09:00:00
ts = np.datetime64(ts, unit)
return convert_to_tsobject(ts, tz, None, False, False)

ts = ts * cast_from_unit(None, unit)
obj.value = ts
dt64_to_dtstruct(ts, &obj.dts)
Expand All @@ -258,7 +264,11 @@ cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit,
obj.value = NPY_NAT
else:
if unit in ["Y", "M"]:
if ts != int(ts):
if ts == int(ts):
# GH#47266 Avoid cast_from_unit, which would give weird results
# e.g. with "Y" and 150.0 we'd get 2120-01-01 09:00:00
return convert_to_tsobject(int(ts), tz, unit, False, False)
else:
# GH#47267 it is clear that 2 "M" corresponds to 1970-02-01,
# but not clear what 2.5 "M" corresponds to, so we will
# disallow that case.
Expand Down
13 changes: 13 additions & 0 deletions pandas/tests/scalar/timestamp/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@


class TestTimestampConstructors:
@pytest.mark.parametrize("typ", [int, float])
def test_constructor_int_float_with_YM_unit(self, typ):
# GH#47266 avoid the conversions in cast_from_unit
val = typ(150)

ts = Timestamp(val, unit="Y")
expected = Timestamp("2120-01-01")
assert ts == expected

ts = Timestamp(val, unit="M")
expected = Timestamp("1982-07-01")
assert ts == expected

def test_constructor_float_not_round_with_YM_unit_deprecated(self):
# GH#47267 avoid the conversions in cast_from-unit

Expand Down

0 comments on commit 3f51046

Please sign in to comment.