Skip to content

Commit 0e484ed

Browse files
authored
REF: consolidate cast_from_unit checks (#50852)
1 parent cda7ba4 commit 0e484ed

File tree

2 files changed

+24
-40
lines changed

2 files changed

+24
-40
lines changed

pandas/_libs/tslib.pyx

+15-33
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,19 @@ def format_array_from_datetime(
220220
return result
221221

222222

223+
cdef int64_t _wrapped_cast_from_unit(object val, str unit) except? -1:
224+
"""
225+
Call cast_from_unit and re-raise OverflowError as OutOfBoundsDatetime
226+
"""
227+
# See also timedeltas._maybe_cast_from_unit
228+
try:
229+
return cast_from_unit(val, unit)
230+
except OverflowError as err:
231+
raise OutOfBoundsDatetime(
232+
f"cannot convert input {val} with the unit '{unit}'"
233+
) from err
234+
235+
223236
def array_with_unit_to_datetime(
224237
ndarray[object] values,
225238
str unit,
@@ -261,13 +274,10 @@ def array_with_unit_to_datetime(
261274
bint is_raise = errors=="raise"
262275
ndarray[int64_t] iresult
263276
object tz = None
264-
bint is_ym
265277
float fval
266278

267279
assert is_ignore or is_coerce or is_raise
268280

269-
is_ym = unit in "YM"
270-
271281
if unit == "ns":
272282
result, tz = array_to_datetime(
273283
values.astype(object, copy=False),
@@ -292,19 +302,7 @@ def array_with_unit_to_datetime(
292302
if val != val or val == NPY_NAT:
293303
iresult[i] = NPY_NAT
294304
else:
295-
if is_ym and is_float_object(val) and not val.is_integer():
296-
# Analogous to GH#47266 for Timestamp
297-
raise ValueError(
298-
f"Conversion of non-round float with unit={unit} "
299-
"is ambiguous"
300-
)
301-
302-
try:
303-
iresult[i] = cast_from_unit(val, unit)
304-
except OverflowError:
305-
raise OutOfBoundsDatetime(
306-
f"cannot convert input {val} with the unit '{unit}'"
307-
)
305+
iresult[i] = _wrapped_cast_from_unit(val, unit)
308306

309307
elif isinstance(val, str):
310308
if len(val) == 0 or val in nat_strings:
@@ -319,23 +317,7 @@ def array_with_unit_to_datetime(
319317
f"non convertible value {val} with the unit '{unit}'"
320318
)
321319

322-
if is_ym and not fval.is_integer():
323-
# Analogous to GH#47266 for Timestamp
324-
raise ValueError(
325-
f"Conversion of non-round float with unit={unit} "
326-
"is ambiguous"
327-
)
328-
329-
try:
330-
iresult[i] = cast_from_unit(fval, unit)
331-
except ValueError:
332-
raise ValueError(
333-
f"non convertible value {val} with the unit '{unit}'"
334-
)
335-
except OverflowError:
336-
raise OutOfBoundsDatetime(
337-
f"cannot convert input {val} with the unit '{unit}'"
338-
)
320+
iresult[i] = _wrapped_cast_from_unit(fval, unit)
339321

340322
else:
341323
# TODO: makes more sense as TypeError, but that would be an

pandas/_libs/tslibs/conversion.pyx

+9-7
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,15 @@ cdef int64_t cast_from_unit(object ts, str unit) except? -1:
108108
if ts is None:
109109
return m
110110

111+
if unit in ["Y", "M"] and is_float_object(ts) and not ts.is_integer():
112+
# GH#47267 it is clear that 2 "M" corresponds to 1970-02-01,
113+
# but not clear what 2.5 "M" corresponds to, so we will
114+
# disallow that case.
115+
raise ValueError(
116+
f"Conversion of non-round float with unit={unit} "
117+
"is ambiguous"
118+
)
119+
111120
# cast the unit, multiply base/frace separately
112121
# to avoid precision issues from float -> int
113122
base = <int64_t>ts
@@ -287,13 +296,6 @@ cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit,
287296
# GH#47266 Avoid cast_from_unit, which would give weird results
288297
# e.g. with "Y" and 150.0 we'd get 2120-01-01 09:00:00
289298
return convert_to_tsobject(int(ts), tz, unit, False, False)
290-
else:
291-
# GH#47267 it is clear that 2 "M" corresponds to 1970-02-01,
292-
# but not clear what 2.5 "M" corresponds to, so we will
293-
# disallow that case.
294-
raise ValueError(
295-
f"Conversion of non-round float with unit={unit} is ambiguous."
296-
)
297299

298300
ts = cast_from_unit(ts, unit)
299301
obj.value = ts

0 commit comments

Comments
 (0)