diff --git a/doc/source/whatsnew/v2.0.1.rst b/doc/source/whatsnew/v2.0.1.rst index fd00f3ed1ff0a..882b600278c88 100644 --- a/doc/source/whatsnew/v2.0.1.rst +++ b/doc/source/whatsnew/v2.0.1.rst @@ -24,6 +24,7 @@ Bug fixes - Bug in :func:`to_datetime` and :func:`to_timedelta` when trying to convert numeric data with a :class:`ArrowDtype` (:issue:`52425`) - Bug in :meth:`Series.describe` not returning :class:`ArrowDtype` with ``pyarrow.float64`` type with numeric data (:issue:`52427`) - Fixed segfault in :meth:`Series.to_numpy` with ``null[pyarrow]`` dtype (:issue:`52443`) +- Bug in :func:`pandas.testing.assert_series_equal` where ``check_dtype=False`` would still raise for datetime or timedelta types with different resolutions (:issue:`52449`) .. --------------------------------------------------------------------------- .. _whatsnew_201.other: diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index 98343148bdad1..196ebd6003d50 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -1,5 +1,6 @@ from __future__ import annotations +import operator from typing import ( Literal, cast, @@ -10,6 +11,7 @@ from pandas._libs.missing import is_matching_na from pandas._libs.sparse import SparseIndex import pandas._libs.testing as _testing +from pandas._libs.tslibs.np_datetime import compare_mismatched_resolutions from pandas.core.dtypes.common import ( is_bool, @@ -23,6 +25,7 @@ ) from pandas.core.dtypes.dtypes import ( CategoricalDtype, + DatetimeTZDtype, PandasDtype, ) from pandas.core.dtypes.missing import array_equivalent @@ -736,6 +739,23 @@ def assert_extension_array_equal( and isinstance(right, DatetimeLikeArrayMixin) and type(right) == type(left) ): + # GH 52449 + if not check_dtype and left.dtype.kind in "mM": + if not isinstance(left.dtype, np.dtype): + l_unit = cast(DatetimeTZDtype, left.dtype).unit + else: + l_unit = np.datetime_data(left.dtype)[0] + if not isinstance(right.dtype, np.dtype): + r_unit = cast(DatetimeTZDtype, left.dtype).unit + else: + r_unit = np.datetime_data(right.dtype)[0] + if ( + l_unit != r_unit + and compare_mismatched_resolutions( + left._ndarray, right._ndarray, operator.eq + ).all() + ): + return # Avoid slow object-dtype comparisons # np.asarray for case where we have a np.MaskedArray assert_numpy_array_equal( diff --git a/pandas/tests/util/test_assert_series_equal.py b/pandas/tests/util/test_assert_series_equal.py index 835f710842cc0..82f5b2fcc6ae7 100644 --- a/pandas/tests/util/test_assert_series_equal.py +++ b/pandas/tests/util/test_assert_series_equal.py @@ -404,3 +404,21 @@ def test_identical_nested_series_is_equal(): tm.assert_series_equal(x, x, check_exact=True) tm.assert_series_equal(x, y) tm.assert_series_equal(x, y, check_exact=True) + + +@pytest.mark.parametrize("dtype", ["datetime64", "timedelta64"]) +def test_check_dtype_false_different_reso(dtype): + # GH 52449 + ser_s = Series([1000213, 2131232, 21312331]).astype(f"{dtype}[s]") + ser_ms = ser_s.astype(f"{dtype}[ms]") + with pytest.raises(AssertionError, match="Attributes of Series are different"): + tm.assert_series_equal(ser_s, ser_ms) + tm.assert_series_equal(ser_ms, ser_s, check_dtype=False) + + ser_ms -= Series([1, 1, 1]).astype(f"{dtype}[ms]") + + with pytest.raises(AssertionError, match="Series are different"): + tm.assert_series_equal(ser_s, ser_ms) + + with pytest.raises(AssertionError, match="Series are different"): + tm.assert_series_equal(ser_s, ser_ms, check_dtype=False)