From 8fc15022e2467d036cf015677feb8a0d701dff9a Mon Sep 17 00:00:00 2001 From: fjdiod Date: Mon, 16 Jul 2018 18:10:15 +0300 Subject: [PATCH 1/4] ENH: add iso-format support to to_timedelta (#21877) --- pandas/_libs/tslibs/timedeltas.pyx | 6 +++++- pandas/tests/scalar/timedelta/test_timedelta.py | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index b9405b15a0980..f7a6cf0c6dafc 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -183,7 +183,11 @@ cpdef convert_to_timedelta64(object ts, object unit): ts = cast_from_unit(ts, unit) ts = np.timedelta64(ts) elif is_string_object(ts): - ts = np.timedelta64(parse_timedelta_string(ts)) + if len(ts) > 0 and ts[0] == 'P': + ts = parse_iso_format_string(ts) + else: + ts = parse_timedelta_string(ts) + ts = np.timedelta64(ts) elif hasattr(ts, 'delta'): ts = np.timedelta64(delta_to_nanoseconds(ts), 'ns') diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py index 6472bd4245622..f394982598865 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -233,6 +233,10 @@ def check(value): assert tup.microseconds == 999 assert tup.nanoseconds == 0 + def test_iso_convertion(self): + expected = Timedelta(1, unit='s') + assert to_timedelta('P0DT0H0M1S') == expected + def test_nat_converters(self): assert to_timedelta('nat', box=False).astype('int64') == iNaT assert to_timedelta('nan', box=False).astype('int64') == iNaT From b5362e5f6aada9782e373e356122e5a627efbcad Mon Sep 17 00:00:00 2001 From: fjdiod Date: Mon, 16 Jul 2018 23:50:55 +0300 Subject: [PATCH 2/4] add test for iso format timedelta in to_timedelta --- pandas/tests/indexes/timedeltas/test_construction.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pandas/tests/indexes/timedeltas/test_construction.py b/pandas/tests/indexes/timedeltas/test_construction.py index 68dc0003e2312..5ad7cbd3258b2 100644 --- a/pandas/tests/indexes/timedeltas/test_construction.py +++ b/pandas/tests/indexes/timedeltas/test_construction.py @@ -44,6 +44,11 @@ def test_constructor(self): tm.assert_index_equal(TimedeltaIndex([400, 450, 1200], unit='ms'), expected) + def test_constructor_iso(self): + expected = timedelta_range('1s', periods=9, freq='s') + durations = ['P0DT0H0M{}S'.format(i) for i in range(1, 10)] + tm.assert_index_equal(to_timedelta(durations), expected) + def test_constructor_coverage(self): rng = timedelta_range('1 days', periods=10.5) exp = timedelta_range('1 days', periods=10) From b8d28f9a6f73fa5d64727eabb283ad39f8674519 Mon Sep 17 00:00:00 2001 From: fjdiod Date: Tue, 17 Jul 2018 18:56:25 +0300 Subject: [PATCH 3/4] add whatsnew entry --- doc/source/whatsnew/v0.24.0.txt | 1 + pandas/tests/indexes/timedeltas/test_construction.py | 4 +++- pandas/tests/scalar/timedelta/test_timedelta.py | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index ed4022d422b4d..04e56c373edc0 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -84,6 +84,7 @@ Other Enhancements - :meth:`Series.nlargest`, :meth:`Series.nsmallest`, :meth:`DataFrame.nlargest`, and :meth:`DataFrame.nsmallest` now accept the value ``"all"`` for the ``keep`` argument. This keeps all ties for the nth largest/smallest value (:issue:`16818`) - :class:`IntervalIndex` has gained the :meth:`~IntervalIndex.set_closed` method to change the existing ``closed`` value (:issue:`21670`) - :func:`~DataFrame.to_csv` and :func:`~DataFrame.to_json` now support ``compression='infer'`` to infer compression based on filename (:issue:`15008`) +- :func:`to_timedelta` now supports iso-formated timedelta strings (:issue:`21877`) - .. _whatsnew_0240.api_breaking: diff --git a/pandas/tests/indexes/timedeltas/test_construction.py b/pandas/tests/indexes/timedeltas/test_construction.py index 5ad7cbd3258b2..447e2b40050f6 100644 --- a/pandas/tests/indexes/timedeltas/test_construction.py +++ b/pandas/tests/indexes/timedeltas/test_construction.py @@ -45,9 +45,11 @@ def test_constructor(self): expected) def test_constructor_iso(self): + # GH #21877 expected = timedelta_range('1s', periods=9, freq='s') durations = ['P0DT0H0M{}S'.format(i) for i in range(1, 10)] - tm.assert_index_equal(to_timedelta(durations), expected) + result = to_timedelta(durations) + tm.assert_index_equal(result, expected) def test_constructor_coverage(self): rng = timedelta_range('1 days', periods=10.5) diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py index f394982598865..0f15b0afd5576 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -234,6 +234,7 @@ def check(value): assert tup.nanoseconds == 0 def test_iso_convertion(self): + # GH #21877 expected = Timedelta(1, unit='s') assert to_timedelta('P0DT0H0M1S') == expected From f0887a8b35ca5f2c602f6646ca98986d46152e93 Mon Sep 17 00:00:00 2001 From: fjdiod Date: Tue, 17 Jul 2018 19:07:51 +0300 Subject: [PATCH 4/4] fix typo --- pandas/tests/scalar/timedelta/test_timedelta.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py index 0f15b0afd5576..017606dc42d59 100644 --- a/pandas/tests/scalar/timedelta/test_timedelta.py +++ b/pandas/tests/scalar/timedelta/test_timedelta.py @@ -233,7 +233,7 @@ def check(value): assert tup.microseconds == 999 assert tup.nanoseconds == 0 - def test_iso_convertion(self): + def test_iso_conversion(self): # GH #21877 expected = Timedelta(1, unit='s') assert to_timedelta('P0DT0H0M1S') == expected