Skip to content

DEPR: Remove errors argument in tz_localize #29911

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 29, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.0.0.rst
Original file line number Diff line number Diff line change
@@ -458,6 +458,7 @@ or ``matplotlib.Axes.plot``. See :ref:`plotting.formatters` for more.
- Changed the default value for the `raw` argument in :func:`Series.rolling().apply() <pandas.core.window.Rolling.apply>`, :func:`DataFrame.rolling().apply() <pandas.core.window.Rolling.apply>`,
- :func:`Series.expanding().apply() <pandas.core.window.Expanding.apply>`, and :func:`DataFrame.expanding().apply() <pandas.core.window.Expanding.apply>` to ``False`` (:issue:`20584`)
- Removed previously deprecated :attr:`Timestamp.weekday_name`, :attr:`DatetimeIndex.weekday_name`, and :attr:`Series.dt.weekday_name` (:issue:`18164`)
- Removed previously deprecated ``errors`` argument in :meth:`Timestamp.tz_localize`, :meth:`DatetimeIndex.tz_localize`, and :meth:`Series.tz_localize` (:issue:`22644`)
-

.. _whatsnew_1000.performance:
12 changes: 0 additions & 12 deletions pandas/_libs/tslibs/nattype.pyx
Original file line number Diff line number Diff line change
@@ -720,18 +720,6 @@ default 'raise'
nonexistent times.
.. versionadded:: 0.24.0
errors : 'raise', 'coerce', default None
Determine how errors should be handled.
The behavior is as follows:
* 'raise' will raise a NonExistentTimeError if a timestamp is not
valid in the specified timezone (e.g. due to a transition from
or to DST time). Use ``nonexistent='raise'`` instead.
* 'coerce' will return NaT if the timestamp can not be converted
into the specified timezone. Use ``nonexistent='NaT'`` instead.
.. deprecated:: 0.24.0
Returns
-------
28 changes: 1 addition & 27 deletions pandas/_libs/tslibs/timestamps.pyx
Original file line number Diff line number Diff line change
@@ -753,8 +753,7 @@ timedelta}, default 'raise'
# GH#21336, GH#21365
return Timedelta(nanoseconds=1)

def tz_localize(self, tz, ambiguous='raise', nonexistent='raise',
errors=None):
def tz_localize(self, tz, ambiguous='raise', nonexistent='raise'):
"""
Convert naive Timestamp to local time zone, or remove
timezone from tz-aware Timestamp.
@@ -797,18 +796,6 @@ default 'raise'
nonexistent times.
.. versionadded:: 0.24.0
errors : 'raise', 'coerce', default None
Determine how errors should be handled.
The behavior is as follows:
* 'raise' will raise a NonExistentTimeError if a timestamp is not
valid in the specified timezone (e.g. due to a transition from
or to DST time). Use ``nonexistent='raise'`` instead.
* 'coerce' will return NaT if the timestamp can not be converted
into the specified timezone. Use ``nonexistent='NaT'`` instead.
.. deprecated:: 0.24.0
Returns
-------
@@ -822,19 +809,6 @@ default 'raise'
if ambiguous == 'infer':
raise ValueError('Cannot infer offset with only one time.')

if errors is not None:
warnings.warn("The errors argument is deprecated and will be "
"removed in a future release. Use "
"nonexistent='NaT' or nonexistent='raise' "
"instead.", FutureWarning)
if errors == 'coerce':
nonexistent = 'NaT'
elif errors == 'raise':
nonexistent = 'raise'
else:
raise ValueError("The errors argument must be either 'coerce' "
"or 'raise'.")

nonexistent_options = ('raise', 'NaT', 'shift_forward',
'shift_backward')
if nonexistent not in nonexistent_options and not isinstance(
30 changes: 1 addition & 29 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
@@ -955,7 +955,7 @@ def tz_convert(self, tz):
dtype = tz_to_dtype(tz)
return self._simple_new(self.asi8, dtype=dtype, freq=self.freq)

def tz_localize(self, tz, ambiguous="raise", nonexistent="raise", errors=None):
def tz_localize(self, tz, ambiguous="raise", nonexistent="raise"):
"""
Localize tz-naive Datetime Array/Index to tz-aware
Datetime Array/Index.
@@ -1004,17 +1004,6 @@ def tz_localize(self, tz, ambiguous="raise", nonexistent="raise", errors=None):
.. versionadded:: 0.24.0
errors : {'raise', 'coerce'}, default None
The method to handle errors:
- 'raise' will raise a NonExistentTimeError if a timestamp is not
valid in the specified time zone (e.g. due to a transition from
or to DST time). Use ``nonexistent='raise'`` instead.
- 'coerce' will return NaT if the timestamp can not be converted
to the specified time zone. Use ``nonexistent='NaT'`` instead.
.. deprecated:: 0.24.0
Returns
-------
Same type as self
@@ -1105,23 +1094,6 @@ def tz_localize(self, tz, ambiguous="raise", nonexistent="raise", errors=None):
1 2015-03-29 03:30:00+02:00
dtype: datetime64[ns, 'Europe/Warsaw']
"""
if errors is not None:
warnings.warn(
"The errors argument is deprecated and will be "
"removed in a future release. Use "
"nonexistent='NaT' or nonexistent='raise' "
"instead.",
FutureWarning,
)
if errors == "coerce":
nonexistent = "NaT"
elif errors == "raise":
nonexistent = "raise"
else:
raise ValueError(
"The errors argument must be either 'coerce' or 'raise'."
)

nonexistent_options = ("raise", "NaT", "shift_forward", "shift_backward")
if nonexistent not in nonexistent_options and not isinstance(
nonexistent, timedelta
22 changes: 2 additions & 20 deletions pandas/tests/indexes/datetimes/test_timezones.py
Original file line number Diff line number Diff line change
@@ -323,13 +323,9 @@ def test_dti_tz_localize_nonexistent_raise_coerce(self):
index.tz_localize(tz=tz)

with pytest.raises(pytz.NonExistentTimeError):
with tm.assert_produces_warning(FutureWarning):
index.tz_localize(tz=tz, errors="raise")
index.tz_localize(tz=tz, nonexistent="raise")

with tm.assert_produces_warning(
FutureWarning, clear=FutureWarning, check_stacklevel=False
):
result = index.tz_localize(tz=tz, errors="coerce")
result = index.tz_localize(tz=tz, nonexistent="NaT")
test_times = ["2015-03-08 01:00-05:00", "NaT", "2015-03-08 03:00-04:00"]
dti = to_datetime(test_times, utc=True)
expected = dti.tz_convert("US/Eastern")
@@ -704,20 +700,6 @@ def test_dti_tz_localize_nonexistent_shift_invalid(self, offset, tz_type):
with pytest.raises(ValueError, match=msg):
dti.tz_localize(tz, nonexistent=timedelta(seconds=offset))

@pytest.mark.filterwarnings("ignore::FutureWarning")
def test_dti_tz_localize_errors_deprecation(self):
# GH 22644
tz = "Europe/Warsaw"
n = 60
dti = date_range(start="2015-03-29 02:00:00", periods=n, freq="min")
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
with pytest.raises(ValueError):
dti.tz_localize(tz, errors="foo")
# make sure errors='coerce' gets mapped correctly to nonexistent
result = dti.tz_localize(tz, errors="coerce")
expected = dti.tz_localize(tz, nonexistent="NaT")
tm.assert_index_equal(result, expected)

# -------------------------------------------------------------
# DatetimeIndex.normalize

29 changes: 6 additions & 23 deletions pandas/tests/scalar/timestamp/test_timezones.py
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@
import pandas.util._test_decorators as td

from pandas import NaT, Timestamp
import pandas.util.testing as tm


class TestTimestampTZOperations:
@@ -80,44 +79,28 @@ def test_tz_localize_ambiguous(self):
("2015-03-29 02:30", "Europe/Belgrade"),
],
)
@pytest.mark.filterwarnings("ignore::FutureWarning")
def test_tz_localize_nonexistent(self, stamp, tz):
# GH#13057
ts = Timestamp(stamp)
with pytest.raises(NonExistentTimeError):
ts.tz_localize(tz)
# GH 22644
with pytest.raises(NonExistentTimeError):
with tm.assert_produces_warning(FutureWarning):
ts.tz_localize(tz, errors="raise")
with tm.assert_produces_warning(FutureWarning):
assert ts.tz_localize(tz, errors="coerce") is NaT
ts.tz_localize(tz, nonexistent="raise")
assert ts.tz_localize(tz, nonexistent="NaT") is NaT

def test_tz_localize_errors_ambiguous(self):
def test_tz_localize_ambiguous_raise(self):
# GH#13057
ts = Timestamp("2015-11-1 01:00")
with pytest.raises(AmbiguousTimeError):
with tm.assert_produces_warning(FutureWarning):
ts.tz_localize("US/Pacific", errors="coerce")
ts.tz_localize("US/Pacific", ambiguous="raise")

@pytest.mark.filterwarnings("ignore::FutureWarning")
def test_tz_localize_errors_invalid_arg(self):
def test_tz_localize_nonexistent_invalid_arg(self):
# GH 22644
tz = "Europe/Warsaw"
ts = Timestamp("2015-03-29 02:00:00")
with pytest.raises(ValueError):
with tm.assert_produces_warning(FutureWarning):
ts.tz_localize(tz, errors="foo")

def test_tz_localize_errors_coerce(self):
# GH 22644
# make sure errors='coerce' gets mapped correctly to nonexistent
tz = "Europe/Warsaw"
ts = Timestamp("2015-03-29 02:00:00")
with tm.assert_produces_warning(FutureWarning):
result = ts.tz_localize(tz, errors="coerce")
expected = ts.tz_localize(tz, nonexistent="NaT")
assert result is expected
ts.tz_localize(tz, nonexistent="foo")

@pytest.mark.parametrize(
"stamp",
15 changes: 0 additions & 15 deletions pandas/tests/series/test_timezones.py
Original file line number Diff line number Diff line change
@@ -33,21 +33,6 @@ def test_series_tz_localize(self):
with pytest.raises(TypeError, match="Already tz-aware"):
ts.tz_localize("US/Eastern")

@pytest.mark.filterwarnings("ignore::FutureWarning")
def test_tz_localize_errors_deprecation(self):
# GH 22644
tz = "Europe/Warsaw"
n = 60
rng = date_range(start="2015-03-29 02:00:00", periods=n, freq="min")
ts = Series(rng)
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
with pytest.raises(ValueError):
ts.dt.tz_localize(tz, errors="foo")
# make sure errors='coerce' gets mapped correctly to nonexistent
result = ts.dt.tz_localize(tz, errors="coerce")
expected = ts.dt.tz_localize(tz, nonexistent="NaT")
tm.assert_series_equal(result, expected)

def test_series_tz_localize_ambiguous_bool(self):
# make sure that we are correctly accepting bool values as ambiguous