@@ -37,7 +37,6 @@ from pandas._libs.tslibs.np_datetime cimport (
37
37
NPY_FR_us,
38
38
check_dts_bounds,
39
39
convert_reso,
40
- get_conversion_factor,
41
40
get_datetime64_unit,
42
41
get_datetime64_value,
43
42
get_implementation_bounds,
@@ -84,9 +83,9 @@ TD64NS_DTYPE = np.dtype("m8[ns]")
84
83
# Unit Conversion Helpers
85
84
86
85
cdef int64_t cast_from_unit(
87
- object ts,
88
- str unit,
89
- NPY_DATETIMEUNIT out_reso = NPY_FR_ns
86
+ object ts,
87
+ str unit,
88
+ NPY_DATETIMEUNIT out_reso = NPY_FR_ns
90
89
) except ? - 1 :
91
90
"""
92
91
Return a casting of the unit represented to nanoseconds
@@ -107,6 +106,10 @@ cdef int64_t cast_from_unit(
107
106
108
107
m, p = precision_from_unit(unit, out_reso)
109
108
109
+ # just give me the unit back
110
+ if ts is None :
111
+ return m
112
+
110
113
if unit in [" Y" , " M" ]:
111
114
if is_float_object(ts) and not ts.is_integer():
112
115
# GH#47267 it is clear that 2 "M" corresponds to 1970-02-01,
@@ -145,8 +148,8 @@ cdef int64_t cast_from_unit(
145
148
146
149
147
150
cpdef inline (int64_t, int ) precision_from_unit(
148
- str unit,
149
- NPY_DATETIMEUNIT out_reso = NPY_DATETIMEUNIT.NPY_FR_ns,
151
+ str unit,
152
+ NPY_DATETIMEUNIT out_reso = NPY_DATETIMEUNIT.NPY_FR_ns,
150
153
):
151
154
"""
152
155
Return a casting of the unit represented to nanoseconds + the precision
@@ -159,14 +162,38 @@ cpdef inline (int64_t, int) precision_from_unit(
159
162
"""
160
163
cdef:
161
164
int64_t m
165
+ int64_t multiplier
162
166
int p
163
167
NPY_DATETIMEUNIT reso = abbrev_to_npy_unit(unit)
164
168
165
- if reso == NPY_DATETIMEUNIT.NPY_FR_GENERIC:
166
- reso = NPY_FR_ns
167
-
168
- m = get_conversion_factor(reso, out_reso)
169
-
169
+ multiplier = periods_per_second(out_reso)
170
+
171
+ if reso == NPY_DATETIMEUNIT.NPY_FR_Y:
172
+ # each 400 years we have 97 leap years, for an average of 97/400=.2425
173
+ # extra days each year. We get 31556952 by writing
174
+ # 3600*24*365.2425=31556952
175
+ m = multiplier * 31556952
176
+ elif reso == NPY_DATETIMEUNIT.NPY_FR_M:
177
+ # 2629746 comes from dividing the "Y" case by 12.
178
+ m = multiplier * 2629746
179
+ elif reso == NPY_DATETIMEUNIT.NPY_FR_W:
180
+ m = multiplier * 3600 * 24 * 7
181
+ elif reso == NPY_DATETIMEUNIT.NPY_FR_D:
182
+ m = multiplier * 3600 * 24
183
+ elif reso == NPY_DATETIMEUNIT.NPY_FR_h:
184
+ m = multiplier * 3600
185
+ elif reso == NPY_DATETIMEUNIT.NPY_FR_m:
186
+ m = multiplier * 60
187
+ elif reso == NPY_DATETIMEUNIT.NPY_FR_s:
188
+ m = multiplier
189
+ elif reso == NPY_DATETIMEUNIT.NPY_FR_ms:
190
+ m = multiplier // 1 _000
191
+ elif reso == NPY_DATETIMEUNIT.NPY_FR_us:
192
+ m = multiplier // 1 _000_000
193
+ elif reso == NPY_DATETIMEUNIT.NPY_FR_ns or reso == NPY_DATETIMEUNIT.NPY_FR_GENERIC:
194
+ m = multiplier // 1 _000_000_000
195
+ else :
196
+ raise ValueError (f" cannot cast unit {unit}" )
170
197
p = < int > log10(m) # number of digits in 'm' minus 1
171
198
return m, p
172
199
0 commit comments