|
3 | 3 | """
|
4 | 4 |
|
5 | 5 | import numpy as np
|
| 6 | +import pandas as pd |
6 | 7 | import pandas.tslib as tslib
|
| 8 | + |
7 | 9 | from pandas.types.common import (_ensure_object,
|
8 | 10 | is_integer_dtype,
|
9 | 11 | is_timedelta64_dtype,
|
@@ -64,37 +66,22 @@ def to_timedelta(arg, unit='ns', box=True, errors='raise', coerce=None):
|
64 | 66 | """
|
65 | 67 | unit = _validate_timedelta_unit(unit)
|
66 | 68 |
|
67 |
| - def _convert_listlike(arg, box, unit, name=None): |
68 |
| - |
69 |
| - if isinstance(arg, (list, tuple)) or not hasattr(arg, 'dtype'): |
70 |
| - arg = np.array(list(arg), dtype='O') |
71 |
| - |
72 |
| - # these are shortcutable |
73 |
| - if is_timedelta64_dtype(arg): |
74 |
| - value = arg.astype('timedelta64[ns]') |
75 |
| - elif is_integer_dtype(arg): |
76 |
| - value = arg.astype('timedelta64[{0}]'.format( |
77 |
| - unit)).astype('timedelta64[ns]', copy=False) |
78 |
| - else: |
79 |
| - value = tslib.array_to_timedelta64(_ensure_object(arg), |
80 |
| - unit=unit, errors=errors) |
81 |
| - value = value.astype('timedelta64[ns]', copy=False) |
82 |
| - |
83 |
| - if box: |
84 |
| - from pandas import TimedeltaIndex |
85 |
| - value = TimedeltaIndex(value, unit='ns', name=name) |
86 |
| - return value |
| 69 | + if errors not in ('ignore', 'raise', 'coerce'): |
| 70 | + raise ValueError("errors must be one of 'ignore', " |
| 71 | + "'raise', or 'coerce'}") |
87 | 72 |
|
88 | 73 | if arg is None:
|
89 | 74 | return arg
|
90 | 75 | elif isinstance(arg, ABCSeries):
|
91 | 76 | from pandas import Series
|
92 |
| - values = _convert_listlike(arg._values, box=False, unit=unit) |
93 |
| - return Series(values, index=arg.index, name=arg.name, dtype='m8[ns]') |
| 77 | + values = _convert_listlike(arg._values, unit=unit, |
| 78 | + box=False, errors=errors) |
| 79 | + return Series(values, index=arg.index, name=arg.name) |
94 | 80 | elif isinstance(arg, ABCIndexClass):
|
95 |
| - return _convert_listlike(arg, box=box, unit=unit, name=arg.name) |
| 81 | + return _convert_listlike(arg, unit=unit, box=box, |
| 82 | + errors=errors, name=arg.name) |
96 | 83 | elif is_list_like(arg) and getattr(arg, 'ndim', 1) == 1:
|
97 |
| - return _convert_listlike(arg, box=box, unit=unit) |
| 84 | + return _convert_listlike(arg, unit=unit, box=box, errors=errors) |
98 | 85 | elif getattr(arg, 'ndim', 1) > 1:
|
99 | 86 | raise TypeError('arg must be a string, timedelta, list, tuple, '
|
100 | 87 | '1-d array, or Series')
|
@@ -142,13 +129,55 @@ def _validate_timedelta_unit(arg):
|
142 | 129 |
|
143 | 130 |
|
144 | 131 | def _coerce_scalar_to_timedelta_type(r, unit='ns', box=True, errors='raise'):
|
145 |
| - """ |
146 |
| - convert strings to timedelta; coerce to Timedelta (if box), else |
147 |
| - np.timedelta64 |
148 |
| - """ |
| 132 | + """Convert string 'r' to a timedelta object.""" |
| 133 | + |
| 134 | + try: |
| 135 | + result = tslib.convert_to_timedelta64(r, unit) |
| 136 | + except ValueError: |
| 137 | + if errors == 'raise': |
| 138 | + raise |
| 139 | + elif errors == 'ignore': |
| 140 | + return r |
| 141 | + |
| 142 | + # coerce |
| 143 | + result = pd.NaT |
149 | 144 |
|
150 |
| - result = tslib.convert_to_timedelta(r, unit, errors) |
151 | 145 | if box:
|
152 | 146 | result = tslib.Timedelta(result)
|
153 |
| - |
154 | 147 | return result
|
| 148 | + |
| 149 | + |
| 150 | +def _convert_listlike(arg, unit='ns', box=True, errors='raise', name=None): |
| 151 | + """Convert a list of objects to a timedelta index object.""" |
| 152 | + |
| 153 | + if isinstance(arg, (list, tuple)) or not hasattr(arg, 'dtype'): |
| 154 | + arg = np.array(list(arg), dtype='O') |
| 155 | + |
| 156 | + # these are shortcut-able |
| 157 | + if is_timedelta64_dtype(arg): |
| 158 | + value = arg.astype('timedelta64[ns]') |
| 159 | + elif is_integer_dtype(arg): |
| 160 | + value = arg.astype('timedelta64[{0}]'.format( |
| 161 | + unit)).astype('timedelta64[ns]', copy=False) |
| 162 | + else: |
| 163 | + try: |
| 164 | + value = tslib.array_to_timedelta64(_ensure_object(arg), |
| 165 | + unit=unit, errors=errors) |
| 166 | + value = value.astype('timedelta64[ns]', copy=False) |
| 167 | + except ValueError: |
| 168 | + if errors == 'ignore': |
| 169 | + return arg |
| 170 | + else: |
| 171 | + # This else-block accounts for the cases when errors='raise' |
| 172 | + # and errors='coerce'. If errors == 'raise', these errors |
| 173 | + # should be raised. If errors == 'coerce', we shouldn't |
| 174 | + # expect any errors to be raised, since all parsing errors |
| 175 | + # cause coercion to pd.NaT. However, if an error / bug is |
| 176 | + # introduced that causes an Exception to be raised, we would |
| 177 | + # like to surface it. |
| 178 | + raise |
| 179 | + |
| 180 | + if box: |
| 181 | + from pandas import TimedeltaIndex |
| 182 | + value = TimedeltaIndex(value, unit='ns', name=name) |
| 183 | + return value |
0 commit comments