Skip to content

Commit ab05d74

Browse files
author
Chris Bertinato
committed
DEPR: Deprecate box kwarg for to_timedelta and to_datetime
1 parent aa08416 commit ab05d74

File tree

9 files changed

+130
-65
lines changed

9 files changed

+130
-65
lines changed

doc/source/whatsnew/v0.25.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Deprecations
7979
~~~~~~~~~~~~
8080

8181
- Deprecated the `M (months)` and `Y (year)` `units` parameter of :func: `pandas.to_timedelta`, :func: `pandas.Timedelta` and :func: `pandas.TimedeltaIndex` (:issue:`16344`)
82+
- The functions :func:`pandas.to_datetime` and :func:`pandas.to_timedelta` have deprecated the ``box`` keyword. Use :attr:`Series.values` and :meth:`Timestamp.to_datetime64`/:meth:`Timedelta.to_timedelta64` instead to get an ndarray of values or ``numpy.timestamp64``/``numpy.timedelta64``, respectively (:issue:`24416`)
8283

8384
.. _whatsnew_0250.prior_deprecations:
8485

pandas/core/dtypes/cast.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -794,10 +794,10 @@ def soft_convert_objects(values, datetime=True, numeric=True, timedelta=True,
794794
# Immediate return if coerce
795795
if datetime:
796796
from pandas import to_datetime
797-
return to_datetime(values, errors='coerce', box=False)
797+
return to_datetime(values, errors='coerce').to_numpy()
798798
elif timedelta:
799799
from pandas import to_timedelta
800-
return to_timedelta(values, errors='coerce', box=False)
800+
return to_timedelta(values, errors='coerce').to_numpy()
801801
elif numeric:
802802
from pandas import to_numeric
803803
return to_numeric(values, errors='coerce')

pandas/core/indexes/datetimelike.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ def asobject(self):
300300
return self.astype(object)
301301

302302
def _convert_tolerance(self, tolerance, target):
303-
tolerance = np.asarray(to_timedelta(tolerance, box=False))
303+
tolerance = np.asarray(to_timedelta(tolerance).to_numpy())
304+
304305
if target.size != tolerance.size and tolerance.size > 1:
305306
raise ValueError('list-like tolerance size must match '
306307
'target index size')

pandas/core/tools/datetimes.py

+9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
from pandas import compat
2121
from pandas.core import algorithms
2222

23+
from pandas.util._decorators import deprecate_kwarg
24+
2325

2426
def _guess_datetime_format_for_array(arr, **kwargs):
2527
# Try to guess the format based on the first non-NaN element
@@ -398,6 +400,7 @@ def _adjust_to_origin(arg, origin, unit):
398400
return arg
399401

400402

403+
@deprecate_kwarg(old_arg_name='box', new_arg_name=None)
401404
def to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False,
402405
utc=None, box=True, format=None, exact=True,
403406
unit=None, infer_datetime_format=False, origin='unix',
@@ -444,6 +447,12 @@ def to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False,
444447
445448
- If True returns a DatetimeIndex or Index-like object
446449
- If False returns ndarray of values.
450+
451+
.. deprecated:: 0.24.0
452+
Use :meth:`.to_numpy` or :meth:`Timestamp.to_datetime64`
453+
instead to get an ndarray of values or numpy.datetime64,
454+
respectively.
455+
447456
format : string, default None
448457
strftime to parse time, eg "%d/%m/%Y", note that "%f" will parse
449458
all the way up to nanoseconds.

pandas/core/tools/timedeltas.py

+9
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414

1515
from pandas.core.arrays.timedeltas import sequence_to_td64ns
1616

17+
from pandas.util._decorators import deprecate_kwarg
1718

19+
20+
@deprecate_kwarg(old_arg_name='box', new_arg_name=None)
1821
def to_timedelta(arg, unit='ns', box=True, errors='raise'):
1922
"""
2023
Convert argument to timedelta.
@@ -40,6 +43,12 @@ def to_timedelta(arg, unit='ns', box=True, errors='raise'):
4043
- If True returns a Timedelta/TimedeltaIndex of the results.
4144
- If False returns a numpy.timedelta64 or numpy.darray of
4245
values of dtype timedelta64[ns].
46+
47+
.. deprecated:: 0.24.0
48+
Use :meth:`.to_numpy` or :meth:`Timedelta.to_timedelta64`
49+
instead to get an ndarray of values or numpy.timedelta64,
50+
respectively.
51+
4352
errors : {'ignore', 'raise', 'coerce'}, default 'raise'
4453
- If 'raise', then invalid parsing will raise an exception.
4554
- If 'coerce', then invalid parsing will be set as NaT.

pandas/io/parsers.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3164,11 +3164,11 @@ def converter(*date_cols):
31643164
return tools.to_datetime(
31653165
ensure_object(strs),
31663166
utc=None,
3167-
box=False,
31683167
dayfirst=dayfirst,
31693168
errors='ignore',
31703169
infer_datetime_format=infer_datetime_format
3171-
)
3170+
).to_numpy()
3171+
31723172
except ValueError:
31733173
return tools.to_datetime(
31743174
parsing.try_parse_dates(strs, dayfirst=dayfirst))

pandas/tests/indexes/datetimes/test_tools.py

+46-22
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,13 @@ def test_to_datetime_format_weeks(self, cache):
221221
def test_to_datetime_parse_tzname_or_tzoffset(self, box, const,
222222
fmt, dates, expected_dates):
223223
# GH 13486
224-
result = pd.to_datetime(dates, format=fmt, box=box)
225-
expected = const(expected_dates)
226-
tm.assert_equal(result, expected)
224+
with tm.assert_produces_warning(FutureWarning):
225+
result = pd.to_datetime(dates, format=fmt, box=box)
226+
expected = const(expected_dates)
227+
tm.assert_equal(result, expected)
227228

228-
with pytest.raises(ValueError):
229-
pd.to_datetime(dates, format=fmt, box=box, utc=True)
229+
with pytest.raises(ValueError):
230+
pd.to_datetime(dates, format=fmt, box=box, utc=True)
230231

231232
@pytest.mark.parametrize('offset', [
232233
'+0', '-1foo', 'UTCbar', ':10', '+01:000:01', ''])
@@ -256,7 +257,7 @@ def test_to_datetime_dtarr(self, tz):
256257
result = to_datetime(arr)
257258
assert result is arr
258259

259-
result = to_datetime(arr, box=True)
260+
result = to_datetime(arr)
260261
assert result is arr
261262

262263
def test_to_datetime_pydatetime(self):
@@ -364,7 +365,7 @@ def test_to_datetime_array_of_dt64s(self, cache):
364365
# Assuming all datetimes are in bounds, to_datetime() returns
365366
# an array that is equal to Timestamp() parsing
366367
tm.assert_numpy_array_equal(
367-
pd.to_datetime(dts, box=False, cache=cache),
368+
pd.to_datetime(dts, cache=cache).to_numpy(),
368369
np.array([Timestamp(x).asm8 for x in dts])
369370
)
370371

@@ -376,8 +377,8 @@ def test_to_datetime_array_of_dt64s(self, cache):
376377
pd.to_datetime(dts_with_oob, errors='raise')
377378

378379
tm.assert_numpy_array_equal(
379-
pd.to_datetime(dts_with_oob, box=False, errors='coerce',
380-
cache=cache),
380+
pd.to_datetime(dts_with_oob, errors='coerce',
381+
cache=cache).to_numpy(),
381382
np.array(
382383
[
383384
Timestamp(dts_with_oob[0]).asm8,
@@ -392,8 +393,8 @@ def test_to_datetime_array_of_dt64s(self, cache):
392393
# are converted to their .item(), which depending on the version of
393394
# numpy is either a python datetime.datetime or datetime.date
394395
tm.assert_numpy_array_equal(
395-
pd.to_datetime(dts_with_oob, box=False, errors='ignore',
396-
cache=cache),
396+
pd.to_datetime(dts_with_oob, errors='ignore',
397+
cache=cache).to_numpy(),
397398
np.array(
398399
[dt.item() for dt in dts_with_oob],
399400
dtype='O'
@@ -628,10 +629,14 @@ def test_to_datetime_cache(self, utc, format, box, constructor):
628629
date = '20130101 00:00:00'
629630
test_dates = [date] * 10**5
630631
data = constructor(test_dates)
631-
result = pd.to_datetime(data, utc=utc, format=format, box=box,
632-
cache=True)
633-
expected = pd.to_datetime(data, utc=utc, format=format, box=box,
634-
cache=False)
632+
633+
with tm.assert_produces_warning(FutureWarning):
634+
result = pd.to_datetime(data, utc=utc, format=format, box=box,
635+
cache=True)
636+
637+
with tm.assert_produces_warning(FutureWarning):
638+
expected = pd.to_datetime(data, utc=utc, format=format, box=box,
639+
cache=False)
635640
if box:
636641
tm.assert_index_equal(result, expected)
637642
else:
@@ -684,7 +689,10 @@ def test_iso_8601_strings_with_same_offset(self):
684689
def test_iso_8601_strings_same_offset_no_box(self):
685690
# GH 22446
686691
data = ['2018-01-04 09:01:00+09:00', '2018-01-04 09:02:00+09:00']
687-
result = pd.to_datetime(data, box=False)
692+
693+
with tm.assert_produces_warning(FutureWarning):
694+
result = pd.to_datetime(data, box=False)
695+
688696
expected = np.array([
689697
datetime(2018, 1, 4, 9, 1, tzinfo=pytz.FixedOffset(540)),
690698
datetime(2018, 1, 4, 9, 2, tzinfo=pytz.FixedOffset(540))
@@ -753,6 +761,16 @@ def test_timestamp_utc_true(self, ts, expected):
753761
result = to_datetime(ts, utc=True)
754762
assert result == expected
755763

764+
def test_to_datetime_box_deprecated(self):
765+
expected = np.datetime64('2018-09-09')
766+
767+
# Deprecated - see GH24416
768+
with tm.assert_produces_warning(FutureWarning):
769+
pd.to_datetime(expected, box=False)
770+
771+
result = pd.to_datetime(expected).to_datetime64()
772+
assert result == expected
773+
756774

757775
class TestToDatetimeUnit(object):
758776
@pytest.mark.parametrize('cache', [True, False])
@@ -891,7 +909,7 @@ def test_unit_rounding(self, cache):
891909
def test_unit_ignore_keeps_name(self, cache):
892910
# GH 21697
893911
expected = pd.Index([15e9] * 2, name='name')
894-
result = pd.to_datetime(expected, errors='ignore', box=True, unit='s',
912+
result = pd.to_datetime(expected, errors='ignore', unit='s',
895913
cache=cache)
896914
tm.assert_index_equal(result, expected)
897915

@@ -1052,7 +1070,10 @@ def test_dataframe_box_false(self):
10521070
df = pd.DataFrame({'year': [2015, 2016],
10531071
'month': [2, 3],
10541072
'day': [4, 5]})
1055-
result = pd.to_datetime(df, box=False)
1073+
1074+
with tm.assert_produces_warning(FutureWarning):
1075+
result = pd.to_datetime(df, box=False)
1076+
10561077
expected = np.array(['2015-02-04', '2016-03-05'],
10571078
dtype='datetime64[ns]')
10581079
tm.assert_numpy_array_equal(result, expected)
@@ -1069,8 +1090,7 @@ def test_dataframe_utc_true(self):
10691090

10701091
def test_to_datetime_errors_ignore_utc_true(self):
10711092
# GH 23758
1072-
result = pd.to_datetime([1], unit='s', box=True, utc=True,
1073-
errors='ignore')
1093+
result = pd.to_datetime([1], unit='s', utc=True, errors='ignore')
10741094
expected = DatetimeIndex(['1970-01-01 00:00:01'], tz='UTC')
10751095
tm.assert_index_equal(result, expected)
10761096

@@ -1195,11 +1215,15 @@ def test_to_datetime_types(self, cache):
11951215
def test_to_datetime_unprocessable_input(self, cache, box, klass):
11961216
# GH 4928
11971217
# GH 21864
1198-
result = to_datetime([1, '1'], errors='ignore', cache=cache, box=box)
1218+
with tm.assert_produces_warning(FutureWarning):
1219+
result = to_datetime([1, '1'], errors='ignore', cache=cache,
1220+
box=box)
1221+
11991222
expected = klass(np.array([1, '1'], dtype='O'))
12001223
tm.assert_equal(result, expected)
12011224
msg = "invalid string coercion to datetime"
1202-
with pytest.raises(TypeError, match=msg):
1225+
with (pytest.raises(TypeError, match=msg),
1226+
tm.assert_produces_warning(FutureWarning)):
12031227
to_datetime([1, '1'], errors='raise', cache=cache, box=box)
12041228

12051229
def test_to_datetime_other_datetime64_units(self):

pandas/tests/indexes/timedeltas/test_tools.py

+55-34
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@ def conv(v):
1919

2020
d1 = np.timedelta64(1, 'D')
2121

22-
assert (to_timedelta('1 days 06:05:01.00003', box=False) ==
23-
conv(d1 + np.timedelta64(6 * 3600 + 5 * 60 + 1, 's') +
24-
np.timedelta64(30, 'us')))
25-
assert (to_timedelta('15.5us', box=False) ==
26-
conv(np.timedelta64(15500, 'ns')))
22+
with tm.assert_produces_warning(FutureWarning):
23+
assert (to_timedelta('1 days 06:05:01.00003', box=False) ==
24+
conv(d1 + np.timedelta64(6 * 3600 + 5 * 60 + 1, 's') +
25+
np.timedelta64(30, 'us')))
2726

28-
# empty string
29-
result = to_timedelta('', box=False)
30-
assert result.astype('int64') == iNaT
27+
with tm.assert_produces_warning(FutureWarning):
28+
assert (to_timedelta('15.5us', box=False) ==
29+
conv(np.timedelta64(15500, 'ns')))
30+
31+
# empty string
32+
result = to_timedelta('', box=False)
33+
assert result.astype('int64') == iNaT
3134

3235
result = to_timedelta(['', ''])
3336
assert isna(result).all()
@@ -37,10 +40,11 @@ def conv(v):
3740
expected = pd.Index(np.array([np.timedelta64(1, 's')]))
3841
tm.assert_index_equal(result, expected)
3942

40-
# ints
41-
result = np.timedelta64(0, 'ns')
42-
expected = to_timedelta(0, box=False)
43-
assert result == expected
43+
with tm.assert_produces_warning(FutureWarning):
44+
# ints
45+
result = np.timedelta64(0, 'ns')
46+
expected = to_timedelta(0, box=False)
47+
assert result == expected
4448

4549
# Series
4650
expected = Series([timedelta(days=1), timedelta(days=1, seconds=1)])
@@ -53,16 +57,18 @@ def conv(v):
5357
expected = to_timedelta([0, 10], unit='s')
5458
tm.assert_index_equal(result, expected)
5559

56-
# single element conversion
57-
v = timedelta(seconds=1)
58-
result = to_timedelta(v, box=False)
59-
expected = np.timedelta64(timedelta(seconds=1))
60-
assert result == expected
60+
with tm.assert_produces_warning(FutureWarning):
61+
# single element conversion
62+
v = timedelta(seconds=1)
63+
result = to_timedelta(v, box=False)
64+
expected = np.timedelta64(timedelta(seconds=1))
65+
assert result == expected
6166

62-
v = np.timedelta64(timedelta(seconds=1))
63-
result = to_timedelta(v, box=False)
64-
expected = np.timedelta64(timedelta(seconds=1))
65-
assert result == expected
67+
with tm.assert_produces_warning(FutureWarning):
68+
v = np.timedelta64(timedelta(seconds=1))
69+
result = to_timedelta(v, box=False)
70+
expected = np.timedelta64(timedelta(seconds=1))
71+
assert result == expected
6672

6773
# arrays of various dtypes
6874
arr = np.array([1] * 5, dtype='int64')
@@ -90,22 +96,27 @@ def conv(v):
9096
expected = TimedeltaIndex([np.timedelta64(1, 'D')] * 5)
9197
tm.assert_index_equal(result, expected)
9298

93-
# Test with lists as input when box=false
94-
expected = np.array(np.arange(3) * 1000000000, dtype='timedelta64[ns]')
95-
result = to_timedelta(range(3), unit='s', box=False)
96-
tm.assert_numpy_array_equal(expected, result)
99+
with tm.assert_produces_warning(FutureWarning):
100+
# Test with lists as input when box=false
101+
expected = np.array(np.arange(3) * 1000000000,
102+
dtype='timedelta64[ns]')
103+
result = to_timedelta(range(3), unit='s', box=False)
104+
tm.assert_numpy_array_equal(expected, result)
97105

98-
result = to_timedelta(np.arange(3), unit='s', box=False)
99-
tm.assert_numpy_array_equal(expected, result)
106+
with tm.assert_produces_warning(FutureWarning):
107+
result = to_timedelta(np.arange(3), unit='s', box=False)
108+
tm.assert_numpy_array_equal(expected, result)
100109

101-
result = to_timedelta([0, 1, 2], unit='s', box=False)
102-
tm.assert_numpy_array_equal(expected, result)
110+
with tm.assert_produces_warning(FutureWarning):
111+
result = to_timedelta([0, 1, 2], unit='s', box=False)
112+
tm.assert_numpy_array_equal(expected, result)
103113

104-
# Tests with fractional seconds as input:
105-
expected = np.array(
106-
[0, 500000000, 800000000, 1200000000], dtype='timedelta64[ns]')
107-
result = to_timedelta([0., 0.5, 0.8, 1.2], unit='s', box=False)
108-
tm.assert_numpy_array_equal(expected, result)
114+
with tm.assert_produces_warning(FutureWarning):
115+
# Tests with fractional seconds as input:
116+
expected = np.array(
117+
[0, 500000000, 800000000, 1200000000], dtype='timedelta64[ns]')
118+
result = to_timedelta([0., 0.5, 0.8, 1.2], unit='s', box=False)
119+
tm.assert_numpy_array_equal(expected, result)
109120

110121
def test_to_timedelta_invalid(self):
111122

@@ -173,3 +184,13 @@ def test_to_timedelta_on_missing_values(self):
173184

174185
actual = pd.to_timedelta(pd.NaT)
175186
assert actual.value == timedelta_NaT.astype('int64')
187+
188+
def test_to_timedelta_box_deprecated(self):
189+
result = np.timedelta64(0, 'ns')
190+
191+
# Deprecated - see GH24416
192+
with tm.assert_produces_warning(FutureWarning):
193+
to_timedelta(0, box=False)
194+
195+
expected = to_timedelta(0).to_timedelta64()
196+
assert result == expected

pandas/tests/scalar/timedelta/test_timedelta.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -310,12 +310,12 @@ def test_iso_conversion(self):
310310
assert to_timedelta('P0DT0H0M1S') == expected
311311

312312
def test_nat_converters(self):
313-
result = to_timedelta('nat', box=False)
314-
assert result.dtype.kind == 'm'
313+
result = to_timedelta('nat').to_numpy()
314+
assert result.dtype.kind == 'M'
315315
assert result.astype('int64') == iNaT
316316

317-
result = to_timedelta('nan', box=False)
318-
assert result.dtype.kind == 'm'
317+
result = to_timedelta('nan').to_numpy()
318+
assert result.dtype.kind == 'M'
319319
assert result.astype('int64') == iNaT
320320

321321
@pytest.mark.filterwarnings("ignore:M and Y units are deprecated")

0 commit comments

Comments
 (0)