@@ -108,22 +108,41 @@ cdef int64_t cast_from_unit(object ts, str unit) except? -1:
108
108
if ts is None :
109
109
return m
110
110
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
- )
111
+ if unit in [" Y" , " M" ]:
112
+ if is_float_object(ts) and not ts.is_integer():
113
+ # GH#47267 it is clear that 2 "M" corresponds to 1970-02-01,
114
+ # but not clear what 2.5 "M" corresponds to, so we will
115
+ # disallow that case.
116
+ raise ValueError (
117
+ f" Conversion of non-round float with unit={unit} "
118
+ " is ambiguous"
119
+ )
120
+ # GH#47266 go through np.datetime64 to avoid weird results e.g. with "Y"
121
+ # and 150 we'd get 2120-01-01 09:00:00
122
+ if is_float_object(ts):
123
+ ts = int (ts)
124
+ dt64obj = np.datetime64(ts, unit)
125
+ return get_datetime64_nanos(dt64obj, NPY_FR_ns)
119
126
120
127
# cast the unit, multiply base/frace separately
121
128
# to avoid precision issues from float -> int
122
- base = < int64_t> ts
129
+ try :
130
+ base = < int64_t> ts
131
+ except OverflowError as err:
132
+ raise OutOfBoundsDatetime(
133
+ f" cannot convert input {ts} with the unit '{unit}'"
134
+ ) from err
135
+
123
136
frac = ts - base
124
137
if p:
125
138
frac = round (frac, p)
126
- return < int64_t> (base * m) + < int64_t> (frac * m)
139
+
140
+ try :
141
+ return < int64_t> (base * m) + < int64_t> (frac * m)
142
+ except OverflowError as err:
143
+ raise OutOfBoundsDatetime(
144
+ f" cannot convert input {ts} with the unit '{unit}'"
145
+ ) from err
127
146
128
147
129
148
cpdef inline (int64_t, int ) precision_from_unit(str unit):
@@ -278,25 +297,13 @@ cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit,
278
297
if ts == NPY_NAT:
279
298
obj.value = NPY_NAT
280
299
else :
281
- if unit in [" Y" , " M" ]:
282
- # GH#47266 cast_from_unit leads to weird results e.g. with "Y"
283
- # and 150 we'd get 2120-01-01 09:00:00
284
- ts = np.datetime64(ts, unit)
285
- return convert_to_tsobject(ts, tz, None , False , False )
286
-
287
- ts = ts * cast_from_unit(None , unit)
300
+ ts = cast_from_unit(ts, unit)
288
301
obj.value = ts
289
302
pandas_datetime_to_datetimestruct(ts, NPY_FR_ns, & obj.dts)
290
303
elif is_float_object(ts):
291
304
if ts != ts or ts == NPY_NAT:
292
305
obj.value = NPY_NAT
293
306
else :
294
- if unit in [" Y" , " M" ]:
295
- if ts == int (ts):
296
- # GH#47266 Avoid cast_from_unit, which would give weird results
297
- # e.g. with "Y" and 150.0 we'd get 2120-01-01 09:00:00
298
- return convert_to_tsobject(int (ts), tz, unit, False , False )
299
-
300
307
ts = cast_from_unit(ts, unit)
301
308
obj.value = ts
302
309
pandas_datetime_to_datetimestruct(ts, NPY_FR_ns, & obj.dts)
0 commit comments