Skip to content

Commit 63717f5

Browse files
author
Chris Bertinato
committed
DEPR: Deprecate box kwarg for to_timedelta and to_datetime
1 parent f886139 commit 63717f5

File tree

9 files changed

+134
-91
lines changed

9 files changed

+134
-91
lines changed

doc/source/whatsnew/v0.25.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ Deprecations
9494
~~~~~~~~~~~~
9595

9696
- Deprecated the `M (months)` and `Y (year)` `units` parameter of :func: `pandas.to_timedelta`, :func: `pandas.Timedelta` and :func: `pandas.TimedeltaIndex` (:issue:`16344`)
97+
- 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`)
9798

9899
.. _whatsnew_0250.prior_deprecations:
99100

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-1
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@
1010
from pandas._libs.tslibs.strptime import array_strptime
1111
from pandas.compat import zip
1212

13+
from pandas.core import algorithms
1314
from pandas.core.dtypes.common import (
1415
ensure_object, is_datetime64_dtype, is_datetime64_ns_dtype,
1516
is_datetime64tz_dtype, is_float, is_integer, is_integer_dtype,
1617
is_list_like, is_numeric_dtype, is_object_dtype, is_scalar)
1718
from pandas.core.dtypes.generic import ABCDataFrame, ABCIndexClass, ABCSeries
1819
from pandas.core.dtypes.missing import notna
20+
from pandas.util._decorators import deprecate_kwarg
1921

2022
from pandas import compat
21-
from pandas.core import algorithms
2223

2324

2425
def _guess_datetime_format_for_array(arr, **kwargs):
@@ -398,6 +399,7 @@ def _adjust_to_origin(arg, origin, unit):
398399
return arg
399400

400401

402+
@deprecate_kwarg(old_arg_name='box', new_arg_name=None)
401403
def to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False,
402404
utc=None, box=True, format=None, exact=True,
403405
unit=None, infer_datetime_format=False, origin='unix',
@@ -444,6 +446,12 @@ def to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False,
444446
445447
- If True returns a DatetimeIndex or Index-like object
446448
- If False returns ndarray of values.
449+
450+
.. deprecated:: 0.25.0
451+
Use :meth:`.to_numpy` or :meth:`Timestamp.to_datetime64`
452+
instead to get an ndarray of values or numpy.datetime64,
453+
respectively.
454+
447455
format : string, default None
448456
strftime to parse time, eg "%d/%m/%Y", note that "%f" will parse
449457
all the way up to nanoseconds.

pandas/core/tools/timedeltas.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
from pandas._libs.tslibs import NaT
1010
from pandas._libs.tslibs.timedeltas import Timedelta, parse_timedelta_unit
1111

12+
from pandas.core.arrays.timedeltas import sequence_to_td64ns
13+
1214
from pandas.core.dtypes.common import is_list_like
1315
from pandas.core.dtypes.generic import ABCIndexClass, ABCSeries
1416

15-
from pandas.core.arrays.timedeltas import sequence_to_td64ns
17+
from pandas.util._decorators import deprecate_kwarg
1618

1719

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.25.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

+49-46
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,6 @@ def test_to_datetime_format_weeks(self, cache):
184184
for s, format, dt in data:
185185
assert to_datetime(s, format=format, cache=cache) == dt
186186

187-
@pytest.mark.parametrize("box,const", [
188-
[True, pd.Index],
189-
[False, np.array]])
190187
@pytest.mark.parametrize("fmt,dates,expected_dates", [
191188
['%Y-%m-%d %H:%M:%S %Z',
192189
['2010-01-01 12:00:00 UTC'] * 2,
@@ -218,15 +215,15 @@ def test_to_datetime_format_weeks(self, cache):
218215
tzinfo=pytz.FixedOffset(0)), # pytz coerces to UTC
219216
pd.Timestamp('2010-01-01 12:00:00',
220217
tzinfo=pytz.FixedOffset(0))]]])
221-
def test_to_datetime_parse_tzname_or_tzoffset(self, box, const,
222-
fmt, dates, expected_dates):
218+
def test_to_datetime_parse_tzname_or_tzoffset(self, fmt, dates,
219+
expected_dates):
223220
# GH 13486
224-
result = pd.to_datetime(dates, format=fmt, box=box)
225-
expected = const(expected_dates)
221+
result = pd.to_datetime(dates, format=fmt)
222+
expected = pd.Index(expected_dates)
226223
tm.assert_equal(result, expected)
227224

228225
with pytest.raises(ValueError):
229-
pd.to_datetime(dates, format=fmt, box=box, utc=True)
226+
pd.to_datetime(dates, format=fmt, utc=True)
230227

231228
@pytest.mark.parametrize('offset', [
232229
'+0', '-1foo', 'UTCbar', ':10', '+01:000:01', ''])
@@ -256,7 +253,7 @@ def test_to_datetime_dtarr(self, tz):
256253
result = to_datetime(arr)
257254
assert result is arr
258255

259-
result = to_datetime(arr, box=True)
256+
result = to_datetime(arr)
260257
assert result is arr
261258

262259
def test_to_datetime_pydatetime(self):
@@ -363,9 +360,9 @@ def test_to_datetime_array_of_dt64s(self, cache):
363360

364361
# Assuming all datetimes are in bounds, to_datetime() returns
365362
# an array that is equal to Timestamp() parsing
366-
tm.assert_numpy_array_equal(
367-
pd.to_datetime(dts, box=False, cache=cache),
368-
np.array([Timestamp(x).asm8 for x in dts])
363+
tm.assert_index_equal(
364+
pd.to_datetime(dts, cache=cache),
365+
pd.DatetimeIndex([Timestamp(x).asm8 for x in dts])
369366
)
370367

371368
# A list of datetimes where the last one is out of bounds
@@ -375,28 +372,26 @@ def test_to_datetime_array_of_dt64s(self, cache):
375372
with pytest.raises(OutOfBoundsDatetime, match=msg):
376373
pd.to_datetime(dts_with_oob, errors='raise')
377374

378-
tm.assert_numpy_array_equal(
379-
pd.to_datetime(dts_with_oob, box=False, errors='coerce',
375+
tm.assert_index_equal(
376+
pd.to_datetime(dts_with_oob, errors='coerce',
380377
cache=cache),
381-
np.array(
378+
pd.DatetimeIndex(
382379
[
383380
Timestamp(dts_with_oob[0]).asm8,
384381
Timestamp(dts_with_oob[1]).asm8,
385-
tslib.iNaT,
386-
],
387-
dtype='M8'
382+
pd.NaT
383+
]
388384
)
389385
)
390386

391387
# With errors='ignore', out of bounds datetime64s
392388
# are converted to their .item(), which depending on the version of
393389
# numpy is either a python datetime.datetime or datetime.date
394-
tm.assert_numpy_array_equal(
395-
pd.to_datetime(dts_with_oob, box=False, errors='ignore',
390+
tm.assert_index_equal(
391+
pd.to_datetime(dts_with_oob, errors='ignore',
396392
cache=cache),
397-
np.array(
398-
[dt.item() for dt in dts_with_oob],
399-
dtype='O'
393+
pd.Index(
394+
[dt.item() for dt in dts_with_oob]
400395
)
401396
)
402397

@@ -622,20 +617,16 @@ def test_datetime_invalid_index(self, values, format, infer):
622617

623618
@pytest.mark.parametrize("utc", [True, None])
624619
@pytest.mark.parametrize("format", ['%Y%m%d %H:%M:%S', None])
625-
@pytest.mark.parametrize("box", [True, False])
626620
@pytest.mark.parametrize("constructor", [list, tuple, np.array, pd.Index])
627-
def test_to_datetime_cache(self, utc, format, box, constructor):
621+
def test_to_datetime_cache(self, utc, format, constructor):
628622
date = '20130101 00:00:00'
629623
test_dates = [date] * 10**5
630624
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)
635-
if box:
636-
tm.assert_index_equal(result, expected)
637-
else:
638-
tm.assert_numpy_array_equal(result, expected)
625+
626+
result = pd.to_datetime(data, utc=utc, format=format, cache=True)
627+
expected = pd.to_datetime(data, utc=utc, format=format, cache=False)
628+
629+
tm.assert_index_equal(result, expected)
639630

640631
@pytest.mark.parametrize("utc", [True, None])
641632
@pytest.mark.parametrize("format", ['%Y%m%d %H:%M:%S', None])
@@ -684,7 +675,10 @@ def test_iso_8601_strings_with_same_offset(self):
684675
def test_iso_8601_strings_same_offset_no_box(self):
685676
# GH 22446
686677
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)
678+
679+
with tm.assert_produces_warning(FutureWarning):
680+
result = pd.to_datetime(data, box=False)
681+
688682
expected = np.array([
689683
datetime(2018, 1, 4, 9, 1, tzinfo=pytz.FixedOffset(540)),
690684
datetime(2018, 1, 4, 9, 2, tzinfo=pytz.FixedOffset(540))
@@ -753,6 +747,16 @@ def test_timestamp_utc_true(self, ts, expected):
753747
result = to_datetime(ts, utc=True)
754748
assert result == expected
755749

750+
def test_to_datetime_box_deprecated(self):
751+
expected = np.datetime64('2018-09-09')
752+
753+
# Deprecated - see GH24416
754+
with tm.assert_produces_warning(FutureWarning):
755+
pd.to_datetime(expected, box=False)
756+
757+
result = pd.to_datetime(expected).to_datetime64()
758+
assert result == expected
759+
756760

757761
class TestToDatetimeUnit(object):
758762
@pytest.mark.parametrize('cache', [True, False])
@@ -891,7 +895,7 @@ def test_unit_rounding(self, cache):
891895
def test_unit_ignore_keeps_name(self, cache):
892896
# GH 21697
893897
expected = pd.Index([15e9] * 2, name='name')
894-
result = pd.to_datetime(expected, errors='ignore', box=True, unit='s',
898+
result = pd.to_datetime(expected, errors='ignore', unit='s',
895899
cache=cache)
896900
tm.assert_index_equal(result, expected)
897901

@@ -1052,7 +1056,10 @@ def test_dataframe_box_false(self):
10521056
df = pd.DataFrame({'year': [2015, 2016],
10531057
'month': [2, 3],
10541058
'day': [4, 5]})
1055-
result = pd.to_datetime(df, box=False)
1059+
1060+
with tm.assert_produces_warning(FutureWarning):
1061+
result = pd.to_datetime(df, box=False)
1062+
10561063
expected = np.array(['2015-02-04', '2016-03-05'],
10571064
dtype='datetime64[ns]')
10581065
tm.assert_numpy_array_equal(result, expected)
@@ -1069,8 +1076,7 @@ def test_dataframe_utc_true(self):
10691076

10701077
def test_to_datetime_errors_ignore_utc_true(self):
10711078
# GH 23758
1072-
result = pd.to_datetime([1], unit='s', box=True, utc=True,
1073-
errors='ignore')
1079+
result = pd.to_datetime([1], unit='s', utc=True, errors='ignore')
10741080
expected = DatetimeIndex(['1970-01-01 00:00:01'], tz='UTC')
10751081
tm.assert_index_equal(result, expected)
10761082

@@ -1188,19 +1194,16 @@ def test_to_datetime_types(self, cache):
11881194
# assert result == expected
11891195

11901196
@pytest.mark.parametrize('cache', [True, False])
1191-
@pytest.mark.parametrize('box, klass', [
1192-
[True, Index],
1193-
[False, np.array]
1194-
])
1195-
def test_to_datetime_unprocessable_input(self, cache, box, klass):
1197+
def test_to_datetime_unprocessable_input(self, cache):
11961198
# GH 4928
11971199
# GH 21864
1198-
result = to_datetime([1, '1'], errors='ignore', cache=cache, box=box)
1199-
expected = klass(np.array([1, '1'], dtype='O'))
1200+
result = to_datetime([1, '1'], errors='ignore', cache=cache)
1201+
1202+
expected = Index(np.array([1, '1'], dtype='O'))
12001203
tm.assert_equal(result, expected)
12011204
msg = "invalid string coercion to datetime"
12021205
with pytest.raises(TypeError, match=msg):
1203-
to_datetime([1, '1'], errors='raise', cache=cache, box=box)
1206+
to_datetime([1, '1'], errors='raise', cache=cache)
12041207

12051208
def test_to_datetime_other_datetime64_units(self):
12061209
# 5/25/2012

0 commit comments

Comments
 (0)