@@ -58,6 +58,7 @@ cdef class Localizer:
58
58
Py_ssize_t ntrans
59
59
const int64_t[::1 ] deltas
60
60
int64_t delta
61
+ int64_t* tdata
61
62
62
63
@ cython.initializedcheck (False )
63
64
@ cython.boundscheck (False )
@@ -68,6 +69,7 @@ cdef class Localizer:
68
69
self .ntrans = - 1 # placeholder
69
70
self .delta = - 1 # placeholder
70
71
self .deltas = _deltas_placeholder
72
+ self .tdata = NULL
71
73
72
74
if is_utc(tz) or tz is None :
73
75
self .use_utc = True
@@ -90,6 +92,57 @@ cdef class Localizer:
90
92
if typ == " pytz" :
91
93
self .use_pytz = True
92
94
95
+ self .tdata = < int64_t* > cnp.PyArray_DATA(self .trans)
96
+
97
+
98
+ @ cython.boundscheck (False )
99
+ @ cython.wraparound (False )
100
+ def tz_convert_from_utc (const int64_t[:] stamps , tzinfo tz ):
101
+ """
102
+ Convert the values (in i8) from UTC to tz
103
+
104
+ Parameters
105
+ ----------
106
+ stamps : ndarray[int64]
107
+ tz : tzinfo
108
+
109
+ Returns
110
+ -------
111
+ ndarray[int64]
112
+ """
113
+ cdef:
114
+ Localizer info = Localizer(tz)
115
+ int64_t utc_val, local_val
116
+ Py_ssize_t pos, i, n = stamps.shape[0 ]
117
+
118
+ int64_t[::1 ] result
119
+
120
+ if tz is None or is_utc(tz) or stamps.size == 0 :
121
+ # Much faster than going through the "standard" pattern below
122
+ return stamps.base.copy()
123
+
124
+ result = np.empty(n, dtype = np.int64)
125
+
126
+ for i in range (n):
127
+ utc_val = stamps[i]
128
+ if utc_val == NPY_NAT:
129
+ result[i] = NPY_NAT
130
+ continue
131
+
132
+ if info.use_utc:
133
+ local_val = utc_val
134
+ elif info.use_tzlocal:
135
+ local_val = utc_val + localize_tzinfo_api(utc_val, tz)
136
+ elif info.use_fixed:
137
+ local_val = utc_val + info.delta
138
+ else :
139
+ pos = bisect_right_i8(info.tdata, utc_val, info.ntrans) - 1
140
+ local_val = utc_val + info.deltas[pos]
141
+
142
+ result[i] = local_val
143
+
144
+ return result.base
145
+
93
146
94
147
# -------------------------------------------------------------------------
95
148
@@ -134,7 +187,6 @@ def ints_to_pydatetime(
134
187
Localizer info = Localizer(tz)
135
188
int64_t utc_val , local_val
136
189
Py_ssize_t pos , i , n = stamps.shape[0 ]
137
- int64_t* tdata = NULL
138
190
139
191
npy_datetimestruct dts
140
192
tzinfo new_tz
@@ -155,9 +207,6 @@ def ints_to_pydatetime(
155
207
"box must be one of 'datetime', 'date', 'time' or 'timestamp'"
156
208
)
157
209
158
- if info.use_dst:
159
- tdata = < int64_t* > cnp.PyArray_DATA(info.trans)
160
-
161
210
for i in range(n ):
162
211
utc_val = stamps[i]
163
212
new_tz = tz
@@ -173,7 +222,7 @@ def ints_to_pydatetime(
173
222
elif info.use_fixed:
174
223
local_val = utc_val + info.delta
175
224
else :
176
- pos = bisect_right_i8(tdata, utc_val, info.ntrans) - 1
225
+ pos = bisect_right_i8(info. tdata, utc_val, info.ntrans) - 1
177
226
local_val = utc_val + info.deltas[pos]
178
227
179
228
if info.use_pytz:
@@ -221,14 +270,10 @@ def get_resolution(const int64_t[:] stamps, tzinfo tz=None) -> Resolution:
221
270
Localizer info = Localizer(tz)
222
271
int64_t utc_val , local_val
223
272
Py_ssize_t pos , i , n = stamps.shape[0 ]
224
- int64_t* tdata = NULL
225
273
226
274
npy_datetimestruct dts
227
275
c_Resolution reso = c_Resolution.RESO_DAY, curr_reso
228
276
229
- if info.use_dst:
230
- tdata = < int64_t* > cnp.PyArray_DATA(info.trans)
231
-
232
277
for i in range(n ):
233
278
utc_val = stamps[i]
234
279
if utc_val == NPY_NAT:
@@ -241,7 +286,7 @@ def get_resolution(const int64_t[:] stamps, tzinfo tz=None) -> Resolution:
241
286
elif info.use_fixed:
242
287
local_val = utc_val + info.delta
243
288
else :
244
- pos = bisect_right_i8(tdata, utc_val, info.ntrans) - 1
289
+ pos = bisect_right_i8(info. tdata, utc_val, info.ntrans) - 1
245
290
local_val = utc_val + info.deltas[pos]
246
291
247
292
dt64_to_dtstruct(local_val, & dts)
@@ -277,13 +322,9 @@ cpdef ndarray[int64_t] normalize_i8_timestamps(const int64_t[:] stamps, tzinfo t
277
322
Localizer info = Localizer(tz)
278
323
int64_t utc_val, local_val
279
324
Py_ssize_t pos, i, n = stamps.shape[0 ]
280
- int64_t* tdata = NULL
281
325
282
326
int64_t[::1 ] result = np.empty(n, dtype = np.int64)
283
327
284
- if info.use_dst:
285
- tdata = < int64_t* > cnp.PyArray_DATA(info.trans)
286
-
287
328
for i in range (n):
288
329
utc_val = stamps[i]
289
330
if utc_val == NPY_NAT:
@@ -297,7 +338,7 @@ cpdef ndarray[int64_t] normalize_i8_timestamps(const int64_t[:] stamps, tzinfo t
297
338
elif info.use_fixed:
298
339
local_val = utc_val + info.delta
299
340
else :
300
- pos = bisect_right_i8(tdata, utc_val, info.ntrans) - 1
341
+ pos = bisect_right_i8(info. tdata, utc_val, info.ntrans) - 1
301
342
local_val = utc_val + info.deltas[pos]
302
343
303
344
result[i] = local_val - (local_val % DAY_NANOS)
@@ -326,10 +367,6 @@ def is_date_array_normalized(const int64_t[:] stamps, tzinfo tz=None) -> bool:
326
367
Localizer info = Localizer(tz)
327
368
int64_t utc_val , local_val
328
369
Py_ssize_t pos , i , n = stamps.shape[0 ]
329
- int64_t* tdata = NULL
330
-
331
- if info.use_dst:
332
- tdata = < int64_t* > cnp.PyArray_DATA(info.trans)
333
370
334
371
for i in range(n ):
335
372
utc_val = stamps[i]
@@ -340,7 +377,7 @@ def is_date_array_normalized(const int64_t[:] stamps, tzinfo tz=None) -> bool:
340
377
elif info.use_fixed:
341
378
local_val = utc_val + info.delta
342
379
else :
343
- pos = bisect_right_i8(tdata, utc_val, info.ntrans) - 1
380
+ pos = bisect_right_i8(info. tdata, utc_val, info.ntrans) - 1
344
381
local_val = utc_val + info.deltas[pos]
345
382
346
383
if local_val % DAY_NANOS != 0 :
@@ -360,15 +397,11 @@ def dt64arr_to_periodarr(ndarray stamps, int freq, tzinfo tz):
360
397
Localizer info = Localizer(tz)
361
398
Py_ssize_t pos, i, n = stamps.size
362
399
int64_t utc_val, local_val, res_val
363
- int64_t* tdata = NULL
364
400
365
401
npy_datetimestruct dts
366
402
ndarray result = cnp.PyArray_EMPTY(stamps.ndim, stamps.shape, cnp.NPY_INT64, 0 )
367
403
cnp.broadcast mi = cnp.PyArray_MultiIterNew2(result, stamps)
368
404
369
- if info.use_dst:
370
- tdata = < int64_t* > cnp.PyArray_DATA(info.trans)
371
-
372
405
for i in range (n):
373
406
# Analogous to: utc_val = stamps[i]
374
407
utc_val = (< int64_t* > cnp.PyArray_MultiIter_DATA(mi, 1 ))[0 ]
@@ -383,7 +416,7 @@ def dt64arr_to_periodarr(ndarray stamps, int freq, tzinfo tz):
383
416
elif info.use_fixed:
384
417
local_val = utc_val + info.delta
385
418
else :
386
- pos = bisect_right_i8(tdata, utc_val, info.ntrans) - 1
419
+ pos = bisect_right_i8(info. tdata, utc_val, info.ntrans) - 1
387
420
local_val = utc_val + info.deltas[pos]
388
421
389
422
dt64_to_dtstruct(local_val, & dts)
0 commit comments