@@ -37,6 +37,7 @@ from pandas._libs.tslibs.np_datetime cimport (
3737 NPY_FR_us,
3838 check_dts_bounds,
3939 convert_reso,
40+ get_conversion_factor,
4041 get_datetime64_unit,
4142 get_datetime64_value,
4243 get_implementation_bounds,
@@ -83,9 +84,9 @@ TD64NS_DTYPE = np.dtype("m8[ns]")
8384# Unit Conversion Helpers
8485
8586cdef int64_t cast_from_unit(
86- object ts,
87- str unit,
88- NPY_DATETIMEUNIT out_reso = NPY_FR_ns
87+ object ts,
88+ str unit,
89+ NPY_DATETIMEUNIT out_reso = NPY_FR_ns
8990) except ? - 1 :
9091 """
9192 Return a casting of the unit represented to nanoseconds
@@ -104,12 +105,6 @@ cdef int64_t cast_from_unit(
104105 int64_t m
105106 int p
106107
107- m, p = precision_from_unit(unit, out_reso)
108-
109- # just give me the unit back
110- if ts is None :
111- return m
112-
113108 if unit in [" Y" , " M" ]:
114109 if is_float_object(ts) and not ts.is_integer():
115110 # GH#47267 it is clear that 2 "M" corresponds to 1970-02-01,
@@ -126,6 +121,8 @@ cdef int64_t cast_from_unit(
126121 dt64obj = np.datetime64(ts, unit)
127122 return get_datetime64_nanos(dt64obj, out_reso)
128123
124+ m, p = precision_from_unit(unit, out_reso)
125+
129126 # cast the unit, multiply base/frac separately
130127 # to avoid precision issues from float -> int
131128 try :
@@ -148,8 +145,8 @@ cdef int64_t cast_from_unit(
148145
149146
150147cpdef inline (int64_t, int ) precision_from_unit(
151- str unit,
152- NPY_DATETIMEUNIT out_reso = NPY_DATETIMEUNIT.NPY_FR_ns,
148+ str unit,
149+ NPY_DATETIMEUNIT out_reso = NPY_DATETIMEUNIT.NPY_FR_ns,
153150):
154151 """
155152 Return a casting of the unit represented to nanoseconds + the precision
@@ -166,34 +163,21 @@ cpdef inline (int64_t, int) precision_from_unit(
166163 int p
167164 NPY_DATETIMEUNIT reso = abbrev_to_npy_unit(unit)
168165
169- multiplier = periods_per_second(out_reso)
170-
166+ if reso == NPY_DATETIMEUNIT.NPY_FR_GENERIC:
167+ reso = NPY_DATETIMEUNIT.NPY_FR_ns
171168 if reso == NPY_DATETIMEUNIT.NPY_FR_Y:
172169 # each 400 years we have 97 leap years, for an average of 97/400=.2425
173170 # extra days each year. We get 31556952 by writing
174171 # 3600*24*365.2425=31556952
172+ multiplier = periods_per_second(out_reso)
175173 m = multiplier * 31556952
176174 elif reso == NPY_DATETIMEUNIT.NPY_FR_M:
177175 # 2629746 comes from dividing the "Y" case by 12.
176+ multiplier = periods_per_second(out_reso)
178177 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
195178 else :
196- raise ValueError (f" cannot cast unit {unit}" )
179+ m = get_conversion_factor(reso, out_reso)
180+
197181 p = < int > log10(m) # number of digits in 'm' minus 1
198182 return m, p
199183
0 commit comments