diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 8a7ad077c2a90..4590e2296f633 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -682,6 +682,8 @@ Other Deprecations - Deprecated the ``closed`` argument in :class:`IntervalArray` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`) - Deprecated the ``closed`` argument in :class:`intervaltree` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`) - Deprecated the ``closed`` argument in :class:`ArrowInterval` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`) +- Deprecated allowing ``unit="M"`` or ``unit="Y"`` in :class:`Timestamp` constructor with a non-round float value (:issue:`47267`) +- .. --------------------------------------------------------------------------- .. _whatsnew_150.performance: diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 808f750c18c9d..44335836dc2ee 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -1,5 +1,7 @@ cimport cython +import warnings + import numpy as np cimport numpy as cnp @@ -255,6 +257,18 @@ cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit, if ts != ts or ts == NPY_NAT: obj.value = NPY_NAT else: + if unit in ["Y", "M"]: + if ts != int(ts): + # 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. + warnings.warn( + "Conversion of non-round float with unit={unit} is ambiguous " + "and will raise in a future version.", + FutureWarning, + stacklevel=1, + ) + ts = cast_from_unit(ts, unit) obj.value = ts dt64_to_dtstruct(ts, &obj.dts) diff --git a/pandas/tests/scalar/timestamp/test_constructors.py b/pandas/tests/scalar/timestamp/test_constructors.py index a5641473c4d52..daf1730df489d 100644 --- a/pandas/tests/scalar/timestamp/test_constructors.py +++ b/pandas/tests/scalar/timestamp/test_constructors.py @@ -25,6 +25,15 @@ class TestTimestampConstructors: + def test_constructor_float_not_round_with_YM_unit_deprecated(self): + # GH#47267 avoid the conversions in cast_from-unit + + with tm.assert_produces_warning(FutureWarning, match="ambiguous"): + Timestamp(150.5, unit="Y") + + with tm.assert_produces_warning(FutureWarning, match="ambiguous"): + Timestamp(150.5, unit="M") + def test_constructor_datetime64_with_tz(self): # GH#42288, GH#24559 dt = np.datetime64("1970-01-01 05:00:00")