diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index c9347b88f2072..6aff4da13b6e6 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -784,6 +784,9 @@ Other - Passing an array with 2 or more dimensions to the :class:`Series` constructor now raises the more specific ``ValueError`` rather than a bare ``Exception`` (:issue:`35744`) - Bug in ``dir`` where ``dir(obj)`` wouldn't show attributes defined on the instance for pandas objects (:issue:`37173`) - Bug in :meth:`RangeIndex.difference` returning :class:`Int64Index` in some cases where it should return :class:`RangeIndex` (:issue:`38028`) +- Fixed bug in :func:`assert_series_equal` when comparing a datetime-like array with an equivalent non extension dtype array (:issue:`37609`) + + .. --------------------------------------------------------------------------- diff --git a/pandas/_testing.py b/pandas/_testing.py index bfff4301c2220..469f5e1bed6ba 100644 --- a/pandas/_testing.py +++ b/pandas/_testing.py @@ -1456,7 +1456,16 @@ def assert_series_equal( check_dtype=check_dtype, index_values=np.asarray(left.index), ) - elif needs_i8_conversion(left.dtype) or needs_i8_conversion(right.dtype): + elif is_extension_array_dtype_and_needs_i8_conversion( + left.dtype, right.dtype + ) or is_extension_array_dtype_and_needs_i8_conversion(right.dtype, left.dtype): + assert_extension_array_equal( + left._values, + right._values, + check_dtype=check_dtype, + index_values=np.asarray(left.index), + ) + elif needs_i8_conversion(left.dtype) and needs_i8_conversion(right.dtype): # DatetimeArray or TimedeltaArray assert_extension_array_equal( left._values, @@ -1866,6 +1875,20 @@ def assert_copy(iter1, iter2, **eql_kwargs): assert elem1 is not elem2, msg +def is_extension_array_dtype_and_needs_i8_conversion(left_dtype, right_dtype) -> bool: + """ + Checks that we have the combination of an ExtensionArraydtype and + a dtype that should be converted to int64 + + Returns + ------- + bool + + Related to issue #37609 + """ + return is_extension_array_dtype(left_dtype) and needs_i8_conversion(right_dtype) + + def getCols(k): return string.ascii_uppercase[:k] diff --git a/pandas/tests/util/test_assert_frame_equal.py b/pandas/tests/util/test_assert_frame_equal.py index 40d2763a13489..8034ace479a62 100644 --- a/pandas/tests/util/test_assert_frame_equal.py +++ b/pandas/tests/util/test_assert_frame_equal.py @@ -272,6 +272,20 @@ def test_assert_frame_equal_ignore_extension_dtype_mismatch(right_dtype): tm.assert_frame_equal(left, right, check_dtype=False) +@pytest.mark.parametrize( + "dtype", + [ + ("timedelta64[ns]"), + ("datetime64[ns, UTC]"), + ("Period[D]"), + ], +) +def test_assert_frame_equal_datetime_like_dtype_mismatch(dtype): + df1 = DataFrame({"a": []}, dtype=dtype) + df2 = DataFrame({"a": []}) + tm.assert_frame_equal(df1, df2, check_dtype=False) + + def test_allows_duplicate_labels(): left = DataFrame() right = DataFrame().set_flags(allows_duplicate_labels=False)