Skip to content
1 change: 1 addition & 0 deletions doc/source/reference/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Exceptions and warnings
errors.PyperclipException
errors.PyperclipWindowsException
errors.SpecificationError
errors.TimezoneDtypeMismatchError
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mroeschke is there a way to address the code smell of parsing error messages without making a ton of new public exceptions?

errors.UndefinedVariableError
errors.UnsortedIndexError
errors.UnsupportedFunctionCall
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
tzconversion,
)
from pandas._libs.tslibs.dtypes import abbrev_to_npy_unit
from pandas.errors import PerformanceWarning
from pandas.errors import PerformanceWarning, TimezoneDtypeMismatchError
from pandas.util._exceptions import find_stack_level
from pandas.util._validators import validate_inclusive

Expand Down Expand Up @@ -2830,7 +2830,7 @@ def _validate_tz_from_dtype(
# We also need to check for the case where the user passed a
# tz-naive dtype (i.e. datetime64[ns])
if tz is not None and not timezones.tz_compare(tz, dtz):
raise ValueError(
raise TimezoneDtypeMismatchError(
"cannot supply both a tz and a "
"timezone-naive dtype (i.e. datetime64[ns])"
)
Expand Down
14 changes: 7 additions & 7 deletions pandas/core/dtypes/cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from pandas.errors import (
IntCastingNaNError,
LossySetitemError,
TimezoneDtypeMismatchError,
)

from pandas.core.dtypes.common import (
Expand Down Expand Up @@ -1095,16 +1096,15 @@ def maybe_cast_to_datetime(
else:
try:
dta = DatetimeArray._from_sequence(value, dtype=dtype)
except ValueError as err:
# We can give a Series-specific exception message.
if "cannot supply both a tz and a timezone-naive dtype" in str(err):
raise ValueError(
except TimezoneDtypeMismatchError as err:
raise ValueError(
"Cannot convert timezone-aware data to "
"timezone-naive dtype. Use "
"pd.Series(values).dt.tz_localize(None) instead."
) from err
raise

) from err
except ValueError:
raise

return dta


Expand Down
11 changes: 11 additions & 0 deletions pandas/errors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,16 @@ class InvalidComparison(Exception):
"""


class TimezoneDtypeMismatchError(ValueError):
"""
Raised when both a separate tz and a tz-naive numpy datetime64 dtype are
supplied (e.g. tz is not None and dtype is datetime64[ns]).

Use case / message:
"cannot supply both a tz and a timezone-naive dtype (i.e. datetime64[ns])"
"""


__all__ = [
"AbstractMethodError",
"AttributeConflictWarning",
Expand Down Expand Up @@ -1081,6 +1091,7 @@ class InvalidComparison(Exception):
"PyperclipException",
"PyperclipWindowsException",
"SpecificationError",
"TimezoneDtypeMismatchError",
"UndefinedVariableError",
"UnsortedIndexError",
"UnsupportedFunctionCall",
Expand Down
3 changes: 2 additions & 1 deletion pandas/tests/indexes/datetimes/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
astype_overflowsafe,
timezones,
)
from pandas.errors import TimezoneDtypeMismatchError

import pandas as pd
from pandas import (
Expand Down Expand Up @@ -709,7 +710,7 @@ def test_constructor_dtype_tz_mismatch_raises(self):
"cannot supply both a tz and a timezone-naive dtype "
r"\(i\.e\. datetime64\[ns\]\)"
)
with pytest.raises(ValueError, match=msg):
with pytest.raises(TimezoneDtypeMismatchError, match=msg):
DatetimeIndex(idx, dtype="datetime64[ns]")

# this is effectively trying to convert tz's
Expand Down
Loading