Skip to content

Commit 48edcad

Browse files
authored
BUG: DataFrame(dt64data, dtype=td64) corner cases (#38792)
1 parent 9b47091 commit 48edcad

File tree

4 files changed

+21
-6
lines changed

4 files changed

+21
-6
lines changed

doc/source/whatsnew/v1.3.0.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ Datetimelike
190190
^^^^^^^^^^^^
191191
- Bug in :class:`DataFrame` and :class:`Series` constructors sometimes dropping nanoseconds from :class:`Timestamp` (resp. :class:`Timedelta`) ``data``, with ``dtype=datetime64[ns]`` (resp. ``timedelta64[ns]``) (:issue:`38032`)
192192
- Bug in :meth:`DataFrame.first` and :meth:`Series.first` returning two months for offset one month when first day is last calendar day (:issue:`29623`)
193-
- Bug in constructing a :class:`DataFrame` or :class:`Series` with mismatched ``datetime64`` data and ``timedelta64`` dtype, or vice-versa, failing to raise ``TypeError`` (:issue:`38575`, :issue:`38764`)
193+
- Bug in constructing a :class:`DataFrame` or :class:`Series` with mismatched ``datetime64`` data and ``timedelta64`` dtype, or vice-versa, failing to raise ``TypeError`` (:issue:`38575`, :issue:`38764`, :issue:`38792`)
194+
- Bug in constructing a :class:`Series` or :class:`DataFrame` with a ``datetime`` object out of bounds for ``datetime64[ns]`` dtype (:issue:`38792`)
194195
- Bug in :meth:`DatetimeIndex.intersection`, :meth:`DatetimeIndex.symmetric_difference`, :meth:`PeriodIndex.intersection`, :meth:`PeriodIndex.symmetric_difference` always returning object-dtype when operating with :class:`CategoricalIndex` (:issue:`38741`)
195196
- Bug in :meth:`Series.where` incorrectly casting ``datetime64`` values to ``int64`` (:issue:`37682`)
196197
-

pandas/core/construction.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -615,9 +615,12 @@ def _try_cast(arr, dtype: Optional[DtypeObj], copy: bool, raise_cast_failure: bo
615615
except OutOfBoundsDatetime:
616616
# in case of out of bound datetime64 -> always raise
617617
raise
618-
except (ValueError, TypeError):
618+
except (ValueError, TypeError) as err:
619619
if dtype is not None and raise_cast_failure:
620620
raise
621+
elif "Cannot cast" in str(err):
622+
# via _disallow_mismatched_datetimelike
623+
raise
621624
else:
622625
subarr = np.array(arr, dtype=object, copy=copy)
623626
return subarr

pandas/core/dtypes/cast.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def maybe_unbox_datetimelike(value: Scalar, dtype: DtypeObj) -> Scalar:
170170
return value
171171

172172

173-
def _disallow_mismatched_datetimelike(value: DtypeObj, dtype: DtypeObj):
173+
def _disallow_mismatched_datetimelike(value, dtype: DtypeObj):
174174
"""
175175
numpy allows np.array(dt64values, dtype="timedelta64[ns]") and
176176
vice-versa, but we do not want to allow this, so we need to
@@ -725,7 +725,11 @@ def infer_dtype_from_scalar(val, pandas_dtype: bool = False) -> Tuple[DtypeObj,
725725
dtype = np.dtype(object)
726726

727727
elif isinstance(val, (np.datetime64, datetime)):
728-
val = Timestamp(val)
728+
try:
729+
val = Timestamp(val)
730+
except OutOfBoundsDatetime:
731+
return np.dtype(object), val
732+
729733
if val is NaT or val.tz is None:
730734
dtype = np.dtype("M8[ns]")
731735
else:
@@ -1472,6 +1476,8 @@ def maybe_cast_to_datetime(value, dtype: Optional[DtypeObj]):
14721476

14731477
# we have an array of datetime or timedeltas & nulls
14741478
elif np.prod(value.shape) or not is_dtype_equal(value.dtype, dtype):
1479+
_disallow_mismatched_datetimelike(value, dtype)
1480+
14751481
try:
14761482
if is_datetime64:
14771483
value = to_datetime(value, errors="raise")

pandas/tests/frame/test_constructors.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -2987,12 +2987,11 @@ def test_from_timedelta64_scalar_object(self, constructor, request):
29872987
def test_from_scalar_datetimelike_mismatched(self, constructor, cls, request):
29882988
node = request.node
29892989
params = node.callspec.params
2990-
if params["frame_or_series"] is DataFrame and params["constructor"] is not None:
2990+
if params["frame_or_series"] is DataFrame and params["constructor"] is dict:
29912991
mark = pytest.mark.xfail(
29922992
reason="DataFrame incorrectly allows mismatched datetimelike"
29932993
)
29942994
node.add_marker(mark)
2995-
29962995
scalar = cls("NaT", "ns")
29972996
dtype = {np.datetime64: "m8[ns]", np.timedelta64: "M8[ns]"}[cls]
29982997

@@ -3002,3 +3001,9 @@ def test_from_scalar_datetimelike_mismatched(self, constructor, cls, request):
30023001
scalar = cls(4, "ns")
30033002
with pytest.raises(TypeError, match="Cannot cast"):
30043003
constructor(scalar, dtype=dtype)
3004+
3005+
def test_from_out_of_bounds_datetime(self, constructor):
3006+
scalar = datetime(9999, 1, 1)
3007+
result = constructor(scalar)
3008+
3009+
assert type(get1(result)) is datetime

0 commit comments

Comments
 (0)