Skip to content

Commit 8f29758

Browse files
authored
PERF: ints_to_pydatetime (#35113)
1 parent 1d26e3a commit 8f29758

File tree

1 file changed

+36
-55
lines changed

1 file changed

+36
-55
lines changed

pandas/_libs/tslib.pyx

+36-55
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ PyDateTime_IMPORT
1515

1616

1717
cimport numpy as cnp
18-
from numpy cimport float64_t, int64_t, ndarray, uint8_t
18+
from numpy cimport float64_t, int64_t, ndarray, uint8_t, intp_t
1919
import numpy as np
2020
cnp.import_array()
2121

@@ -157,13 +157,15 @@ def ints_to_pydatetime(
157157
Py_ssize_t i, n = len(arr)
158158
ndarray[int64_t] trans
159159
int64_t[:] deltas
160-
Py_ssize_t pos
160+
intp_t[:] pos
161161
npy_datetimestruct dts
162162
object dt, new_tz
163163
str typ
164-
int64_t value, delta, local_value
164+
int64_t value, local_value, delta = NPY_NAT # dummy for delta
165165
ndarray[object] result = np.empty(n, dtype=object)
166166
object (*func_create)(int64_t, npy_datetimestruct, tzinfo, object, bint)
167+
bint use_utc = False, use_tzlocal = False, use_fixed = False
168+
bint use_pytz = False
167169

168170
if box == "date":
169171
assert (tz is None), "tz should be None when converting to date"
@@ -184,66 +186,45 @@ def ints_to_pydatetime(
184186
)
185187

186188
if is_utc(tz) or tz is None:
187-
for i in range(n):
188-
value = arr[i]
189-
if value == NPY_NAT:
190-
result[i] = <object>NaT
191-
else:
192-
dt64_to_dtstruct(value, &dts)
193-
result[i] = func_create(value, dts, tz, freq, fold)
189+
use_utc = True
194190
elif is_tzlocal(tz):
195-
for i in range(n):
196-
value = arr[i]
197-
if value == NPY_NAT:
198-
result[i] = <object>NaT
199-
else:
200-
# Python datetime objects do not support nanosecond
201-
# resolution (yet, PEP 564). Need to compute new value
202-
# using the i8 representation.
203-
local_value = tz_convert_utc_to_tzlocal(value, tz)
204-
dt64_to_dtstruct(local_value, &dts)
205-
result[i] = func_create(value, dts, tz, freq, fold)
191+
use_tzlocal = True
206192
else:
207193
trans, deltas, typ = get_dst_info(tz)
208-
209-
if typ not in ['pytz', 'dateutil']:
194+
if typ not in ["pytz", "dateutil"]:
210195
# static/fixed; in this case we know that len(delta) == 1
196+
use_fixed = True
211197
delta = deltas[0]
212-
for i in range(n):
213-
value = arr[i]
214-
if value == NPY_NAT:
215-
result[i] = <object>NaT
216-
else:
217-
# Adjust datetime64 timestamp, recompute datetimestruct
218-
dt64_to_dtstruct(value + delta, &dts)
219-
result[i] = func_create(value, dts, tz, freq, fold)
198+
else:
199+
pos = trans.searchsorted(arr, side="right") - 1
200+
use_pytz = typ == "pytz"
220201

221-
elif typ == 'dateutil':
222-
# no zone-name change for dateutil tzs - dst etc
223-
# represented in single object.
224-
for i in range(n):
225-
value = arr[i]
226-
if value == NPY_NAT:
227-
result[i] = <object>NaT
228-
else:
229-
# Adjust datetime64 timestamp, recompute datetimestruct
230-
pos = trans.searchsorted(value, side='right') - 1
231-
dt64_to_dtstruct(value + deltas[pos], &dts)
232-
result[i] = func_create(value, dts, tz, freq, fold)
202+
for i in range(n):
203+
new_tz = tz
204+
value = arr[i]
205+
206+
if value == NPY_NAT:
207+
result[i] = <object>NaT
233208
else:
234-
# pytz
235-
for i in range(n):
236-
value = arr[i]
237-
if value == NPY_NAT:
238-
result[i] = <object>NaT
239-
else:
240-
# Adjust datetime64 timestamp, recompute datetimestruct
241-
pos = trans.searchsorted(value, side='right') - 1
242-
# find right representation of dst etc in pytz timezone
243-
new_tz = tz._tzinfos[tz._transition_info[pos]]
209+
if use_utc:
210+
local_value = value
211+
elif use_tzlocal:
212+
local_value = tz_convert_utc_to_tzlocal(value, tz)
213+
elif use_fixed:
214+
local_value = value + delta
215+
elif not use_pytz:
216+
# i.e. dateutil
217+
# no zone-name change for dateutil tzs - dst etc
218+
# represented in single object.
219+
local_value = value + deltas[pos[i]]
220+
else:
221+
# pytz
222+
# find right representation of dst etc in pytz timezone
223+
new_tz = tz._tzinfos[tz._transition_info[pos[i]]]
224+
local_value = value + deltas[pos[i]]
244225

245-
dt64_to_dtstruct(value + deltas[pos], &dts)
246-
result[i] = func_create(value, dts, new_tz, freq, fold)
226+
dt64_to_dtstruct(local_value, &dts)
227+
result[i] = func_create(value, dts, new_tz, freq, fold)
247228

248229
return result
249230

0 commit comments

Comments
 (0)