@@ -25,7 +25,6 @@ from pandas._libs.tslibs.np_datetime import OutOfBoundsDatetime
2525from pandas._libs.tslibs.util cimport (
2626 is_datetime64_object, is_integer_object, is_float_object)
2727
28- from pandas._libs.tslibs.timedeltas cimport cast_from_unit
2928from pandas._libs.tslibs.timezones cimport (
3029 is_utc, is_tzlocal, is_fixed_offset, get_utcoffset, get_dst_info,
3130 get_timezone, maybe_get_tz, tz_compare,
@@ -55,7 +54,78 @@ TD64NS_DTYPE = np.dtype('m8[ns]')
5554
5655
5756# ----------------------------------------------------------------------
58- # Misc Helpers
57+ # Unit Conversion Helpers
58+
59+ cdef inline int64_t cast_from_unit(object ts, str unit) except ? - 1 :
60+ """ return a casting of the unit represented to nanoseconds
61+ round the fractional part of a float to our precision, p """
62+ cdef:
63+ int64_t m
64+ int p
65+
66+ m, p = precision_from_unit(unit)
67+
68+ # just give me the unit back
69+ if ts is None :
70+ return m
71+
72+ # cast the unit, multiply base/frace separately
73+ # to avoid precision issues from float -> int
74+ base = < int64_t> ts
75+ frac = ts - base
76+ if p:
77+ frac = round (frac, p)
78+ return < int64_t> (base * m) + < int64_t> (frac * m)
79+
80+
81+ cpdef inline object precision_from_unit(str unit):
82+ """
83+ Return a casting of the unit represented to nanoseconds + the precision
84+ to round the fractional part.
85+
86+ Notes
87+ -----
88+ The caller is responsible for ensuring that the default value of "ns"
89+ takes the place of None.
90+ """
91+ cdef:
92+ int64_t m
93+ int p
94+
95+ if unit == " Y" :
96+ m = 1 _000_000_000 * 31556952
97+ p = 9
98+ elif unit == " M" :
99+ m = 1 _000_000_000 * 2629746
100+ p = 9
101+ elif unit == " W" :
102+ m = 1 _000_000_000 * 3600 * 24 * 7
103+ p = 9
104+ elif unit == " D" or unit == " d" :
105+ m = 1 _000_000_000 * 3600 * 24
106+ p = 9
107+ elif unit == " h" :
108+ m = 1 _000_000_000 * 3600
109+ p = 9
110+ elif unit == " m" :
111+ m = 1 _000_000_000 * 60
112+ p = 9
113+ elif unit == " s" :
114+ m = 1 _000_000_000
115+ p = 9
116+ elif unit == " ms" :
117+ m = 1 _000_000
118+ p = 6
119+ elif unit == " us" :
120+ m = 1000
121+ p = 3
122+ elif unit == " ns" or unit is None :
123+ m = 1
124+ p = 0
125+ else :
126+ raise ValueError (f" cannot cast unit {unit}" )
127+ return m, p
128+
59129
60130cdef inline int64_t get_datetime64_nanos(object val) except ? - 1 :
61131 """
@@ -155,6 +225,9 @@ def ensure_timedelta64ns(arr: ndarray, copy: bool=True):
155225 # TODO: check for overflows when going from a lower-resolution to nanos
156226
157227
228+ # ----------------------------------------------------------------------
229+
230+
158231@ cython.boundscheck (False )
159232@ cython.wraparound (False )
160233def datetime_to_datetime64 (ndarray[object] values ):
0 commit comments