Skip to content

Commit 8f00f59

Browse files
authored
REF: implement utc_val_to_local_val (#46847)
1 parent ec29dfc commit 8f00f59

File tree

1 file changed

+32
-58
lines changed

1 file changed

+32
-58
lines changed

pandas/_libs/tslibs/vectorized.pyx

+32-58
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,31 @@ cdef class Localizer:
8080
else:
8181
trans, deltas, typ = get_dst_info(tz)
8282
self.trans = trans
83-
self.ntrans = trans.shape[0]
83+
self.ntrans = self.trans.shape[0]
8484
self.deltas = deltas
8585

8686
if typ != "pytz" and typ != "dateutil":
8787
# static/fixed; in this case we know that len(delta) == 1
8888
self.use_fixed = True
89-
self.delta = deltas[0]
89+
self.delta = self.deltas[0]
9090
else:
9191
self.use_dst = True
9292
if typ == "pytz":
9393
self.use_pytz = True
94-
9594
self.tdata = <int64_t*>cnp.PyArray_DATA(self.trans)
9695

96+
@cython.boundscheck(False)
97+
cdef inline int64_t utc_val_to_local_val(self, int64_t utc_val, Py_ssize_t* pos) except? -1:
98+
if self.use_utc:
99+
return utc_val
100+
elif self.use_tzlocal:
101+
return utc_val + localize_tzinfo_api(utc_val, self.tz)
102+
elif self.use_fixed:
103+
return utc_val + self.delta
104+
else:
105+
pos[0] = bisect_right_i8(self.tdata, utc_val, self.ntrans) - 1
106+
return utc_val + self.deltas[pos[0]]
107+
97108

98109
@cython.boundscheck(False)
99110
@cython.wraparound(False)
@@ -186,7 +197,8 @@ def ints_to_pydatetime(
186197
cdef:
187198
Localizer info = Localizer(tz)
188199
int64_t utc_val, local_val
189-
Py_ssize_t pos, i, n = stamps.shape[0]
200+
Py_ssize_t i, n = stamps.shape[0]
201+
Py_ssize_t pos = -1 # unused, avoid not-initialized warning
190202

191203
npy_datetimestruct dts
192204
tzinfo new_tz
@@ -215,19 +227,10 @@ def ints_to_pydatetime(
215227
result[i] = <object>NaT
216228
continue
217229

218-
if info.use_utc:
219-
local_val = utc_val
220-
elif info.use_tzlocal:
221-
local_val = utc_val + localize_tzinfo_api(utc_val, tz)
222-
elif info.use_fixed:
223-
local_val = utc_val + info.delta
224-
else:
225-
pos = bisect_right_i8(info.tdata, utc_val, info.ntrans) - 1
226-
local_val = utc_val + info.deltas[pos]
227-
228-
if info.use_pytz:
229-
# find right representation of dst etc in pytz timezone
230-
new_tz = tz._tzinfos[tz._transition_info[pos]]
230+
local_val = info.utc_val_to_local_val(utc_val, &pos)
231+
if info.use_pytz:
232+
# find right representation of dst etc in pytz timezone
233+
new_tz = tz._tzinfos[tz._transition_info[pos]]
231234

232235
dt64_to_dtstruct(local_val, &dts)
233236

@@ -269,7 +272,8 @@ def get_resolution(const int64_t[:] stamps, tzinfo tz=None) -> Resolution:
269272
cdef:
270273
Localizer info = Localizer(tz)
271274
int64_t utc_val, local_val
272-
Py_ssize_t pos, i, n = stamps.shape[0]
275+
Py_ssize_t i, n = stamps.shape[0]
276+
Py_ssize_t pos = -1 # unused, avoid not-initialized warning
273277

274278
npy_datetimestruct dts
275279
c_Resolution reso = c_Resolution.RESO_DAY, curr_reso
@@ -279,15 +283,7 @@ def get_resolution(const int64_t[:] stamps, tzinfo tz=None) -> Resolution:
279283
if utc_val == NPY_NAT:
280284
continue
281285

282-
if info.use_utc:
283-
local_val = utc_val
284-
elif info.use_tzlocal:
285-
local_val = utc_val + localize_tzinfo_api(utc_val, tz)
286-
elif info.use_fixed:
287-
local_val = utc_val + info.delta
288-
else:
289-
pos = bisect_right_i8(info.tdata, utc_val, info.ntrans) - 1
290-
local_val = utc_val + info.deltas[pos]
286+
local_val = info.utc_val_to_local_val(utc_val, &pos)
291287

292288
dt64_to_dtstruct(local_val, &dts)
293289
curr_reso = _reso_stamp(&dts)
@@ -321,7 +317,8 @@ cpdef ndarray[int64_t] normalize_i8_timestamps(const int64_t[:] stamps, tzinfo t
321317
cdef:
322318
Localizer info = Localizer(tz)
323319
int64_t utc_val, local_val
324-
Py_ssize_t pos, i, n = stamps.shape[0]
320+
Py_ssize_t i, n = stamps.shape[0]
321+
Py_ssize_t pos = -1 # unused, avoid not-initialized warning
325322

326323
int64_t[::1] result = np.empty(n, dtype=np.int64)
327324

@@ -331,15 +328,7 @@ cpdef ndarray[int64_t] normalize_i8_timestamps(const int64_t[:] stamps, tzinfo t
331328
result[i] = NPY_NAT
332329
continue
333330

334-
if info.use_utc:
335-
local_val = utc_val
336-
elif info.use_tzlocal:
337-
local_val = utc_val + localize_tzinfo_api(utc_val, tz)
338-
elif info.use_fixed:
339-
local_val = utc_val + info.delta
340-
else:
341-
pos = bisect_right_i8(info.tdata, utc_val, info.ntrans) - 1
342-
local_val = utc_val + info.deltas[pos]
331+
local_val = info.utc_val_to_local_val(utc_val, &pos)
343332

344333
result[i] = local_val - (local_val % DAY_NANOS)
345334

@@ -366,19 +355,12 @@ def is_date_array_normalized(const int64_t[:] stamps, tzinfo tz=None) -> bool:
366355
cdef:
367356
Localizer info = Localizer(tz)
368357
int64_t utc_val, local_val
369-
Py_ssize_t pos, i, n = stamps.shape[0]
358+
Py_ssize_t i, n = stamps.shape[0]
359+
Py_ssize_t pos = -1 # unused, avoid not-initialized warning
370360

371361
for i in range(n):
372362
utc_val = stamps[i]
373-
if info.use_utc:
374-
local_val = utc_val
375-
elif info.use_tzlocal:
376-
local_val = utc_val + localize_tzinfo_api(utc_val, tz)
377-
elif info.use_fixed:
378-
local_val = utc_val + info.delta
379-
else:
380-
pos = bisect_right_i8(info.tdata, utc_val, info.ntrans) - 1
381-
local_val = utc_val + info.deltas[pos]
363+
local_val = info.utc_val_to_local_val(utc_val, &pos)
382364

383365
if local_val % DAY_NANOS != 0:
384366
return False
@@ -395,7 +377,8 @@ def dt64arr_to_periodarr(ndarray stamps, int freq, tzinfo tz):
395377
# stamps is int64_t, arbitrary ndim
396378
cdef:
397379
Localizer info = Localizer(tz)
398-
Py_ssize_t pos, i, n = stamps.size
380+
Py_ssize_t i, n = stamps.size
381+
Py_ssize_t pos = -1 # unused, avoid not-initialized warning
399382
int64_t utc_val, local_val, res_val
400383

401384
npy_datetimestruct dts
@@ -409,16 +392,7 @@ def dt64arr_to_periodarr(ndarray stamps, int freq, tzinfo tz):
409392
if utc_val == NPY_NAT:
410393
res_val = NPY_NAT
411394
else:
412-
if info.use_utc:
413-
local_val = utc_val
414-
elif info.use_tzlocal:
415-
local_val = utc_val + localize_tzinfo_api(utc_val, tz)
416-
elif info.use_fixed:
417-
local_val = utc_val + info.delta
418-
else:
419-
pos = bisect_right_i8(info.tdata, utc_val, info.ntrans) - 1
420-
local_val = utc_val + info.deltas[pos]
421-
395+
local_val = info.utc_val_to_local_val(utc_val, &pos)
422396
dt64_to_dtstruct(local_val, &dts)
423397
res_val = get_period_ordinal(&dts, freq)
424398

0 commit comments

Comments
 (0)