Skip to content

Commit 240d643

Browse files
committed
API: to_timedelta(integers, unit) give requested unit
1 parent 996ce52 commit 240d643

File tree

7 files changed

+29
-16
lines changed

7 files changed

+29
-16
lines changed

pandas/_libs/tslibs/timedeltas.pyx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ from pandas._libs.tslibs.conversion cimport (
4444
cast_from_unit,
4545
)
4646
from pandas._libs.tslibs.dtypes cimport (
47+
abbrev_to_npy_unit,
4748
c_DEPR_UNITS,
4849
get_supported_reso,
4950
is_supported_unit,
@@ -359,11 +360,16 @@ def array_to_timedelta64(
359360
cnp.broadcast mi = cnp.PyArray_MultiIterNew2(result, values)
360361
cnp.flatiter it
361362
str parsed_unit = parse_timedelta_unit(unit or "ns")
362-
NPY_DATETIMEUNIT item_reso
363+
NPY_DATETIMEUNIT item_reso, int_reso
363364
ResoState state = ResoState(creso)
364365
bint infer_reso = creso == NPY_DATETIMEUNIT.NPY_FR_GENERIC
365366
ndarray iresult = result.view("i8")
366367

368+
if unit is None:
369+
int_reso = NPY_FR_ns
370+
else:
371+
int_reso = get_supported_reso(abbrev_to_npy_unit(parsed_unit))
372+
367373
if values.descr.type_num != cnp.NPY_OBJECT:
368374
# raise here otherwise we segfault below
369375
raise TypeError("array_to_timedelta64 'values' must have object dtype")
@@ -472,7 +478,18 @@ def array_to_timedelta64(
472478
creso = state.creso
473479
ival = delta_to_nanoseconds(item, reso=creso)
474480

475-
elif is_integer_object(item) or is_float_object(item):
481+
elif is_integer_object(item):
482+
if item == NPY_NAT:
483+
ival = NPY_NAT
484+
else:
485+
ival = _numeric_to_td64ns(item, parsed_unit, int_reso)
486+
item_reso = int_reso
487+
488+
state.update_creso(item_reso)
489+
if infer_reso:
490+
creso = state.creso
491+
492+
elif is_float_object(item):
476493
ival = _numeric_to_td64ns(item, parsed_unit, NPY_FR_ns)
477494

478495
item_reso = NPY_FR_ns

pandas/tests/arithmetic/test_timedelta64.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -729,11 +729,12 @@ def test_tdi_add_overflow(self):
729729
# TODO: Make raised error message more informative and test
730730

731731
_NaT = NaT._value + 1
732+
td = pd.to_timedelta([106580], "D").as_unit("ns")
732733
msg = "Overflow in int64 addition"
733734
with pytest.raises(OverflowError, match=msg):
734-
pd.to_timedelta([106580], "D") + Timestamp("2000")
735+
td + Timestamp("2000")
735736
with pytest.raises(OverflowError, match=msg):
736-
Timestamp("2000") + pd.to_timedelta([106580], "D")
737+
Timestamp("2000") + td
737738
with pytest.raises(OverflowError, match=msg):
738739
pd.to_timedelta([_NaT]) - Timedelta("1 days")
739740
with pytest.raises(OverflowError, match=msg):

pandas/tests/indexes/timedeltas/methods/test_shift.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def test_tdi_shift_int(self):
4949
"5 days 01:00:00",
5050
],
5151
freq="D",
52-
dtype="m8[ns]",
52+
dtype="m8[s]",
5353
)
5454
tm.assert_index_equal(result, expected)
5555

@@ -67,7 +67,7 @@ def test_tdi_shift_nonstandard_freq(self):
6767
"10 days 01:00:03",
6868
],
6969
freq="D",
70-
dtype="m8[ns]",
70+
dtype="m8[s]",
7171
)
7272
tm.assert_index_equal(result, expected)
7373

pandas/tests/indexes/timedeltas/test_constructors.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,5 @@ def test_unit_deprecated(self, unit, unit_depr):
267267

268268
with tm.assert_produces_warning(Pandas4Warning, match=msg):
269269
tdi = to_timedelta([1, 2], unit=unit_depr)
270-
tm.assert_index_equal(tdi, expected.as_unit("ns"))
270+
exp_unit = unit if unit in ["s", "ms", "us"] else "s"
271+
tm.assert_index_equal(tdi, expected.as_unit(exp_unit))

pandas/tests/resample/test_timedelta.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,7 @@ def test_resample_categorical_data_with_timedeltaindex():
101101
df = DataFrame({"Group_obj": "A"}, index=pd.to_timedelta(list(range(20)), unit="s"))
102102
df["Group"] = df["Group_obj"].astype("category")
103103
result = df.resample("10s").agg(lambda x: (x.value_counts().index[0]))
104-
exp_tdi = pd.TimedeltaIndex(np.array([0, 10], dtype="m8[s]"), freq="10s").as_unit(
105-
"ns"
106-
)
104+
exp_tdi = pd.TimedeltaIndex(np.array([0, 10], dtype="m8[s]"), freq="10s")
107105
expected = DataFrame(
108106
{"Group_obj": ["A", "A"], "Group": ["A", "A"]},
109107
index=exp_tdi,

pandas/tests/scalar/timedelta/test_constructors.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,7 @@ def test_unit_deprecated(self, unit, unit_depr):
155155
def test_unit_parser(self, unit, np_unit, wrapper):
156156
# validate all units, GH 6855, GH 21762
157157
# array-likes
158-
if wrapper is list:
159-
# we go through _objects_to_td64ns which hasn't yet been updated
160-
exp_unit = "ns"
161-
else:
162-
exp_unit = np_unit if np_unit not in ["W", "D", "m"] else "s"
158+
exp_unit = np_unit if np_unit not in ["W", "D", "m"] else "s"
163159
expected = TimedeltaIndex(
164160
[np.timedelta64(i, np_unit) for i in np.arange(5).tolist()],
165161
dtype=f"m8[{exp_unit}]",

pandas/tests/tools/test_to_timedelta.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def test_to_timedelta_units(self):
104104
result = TimedeltaIndex(
105105
[np.timedelta64(0, "ns"), np.timedelta64(10, "s").astype("m8[ns]")]
106106
)
107-
expected = to_timedelta([0, 10], unit="s")
107+
expected = to_timedelta([0, 10], unit="s").as_unit("ns")
108108
tm.assert_index_equal(result, expected)
109109

110110
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)