Skip to content

PERF: normalize_i8_timestamps #34672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 9, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 15 additions & 20 deletions pandas/_libs/tslibs/conversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,6 @@ cpdef ndarray[int64_t] normalize_i8_timestamps(const int64_t[:] stamps, tzinfo t
int64_t[:] deltas
str typ
Py_ssize_t[:] pos
npy_datetimestruct dts
int64_t delta, local_val

if tz is None or is_utc(tz):
Expand All @@ -795,16 +794,14 @@ cpdef ndarray[int64_t] normalize_i8_timestamps(const int64_t[:] stamps, tzinfo t
result[i] = NPY_NAT
continue
local_val = stamps[i]
dt64_to_dtstruct(local_val, &dts)
result[i] = _normalized_stamp(&dts)
result[i] = _normalize_i8_stamp(local_val)
elif is_tzlocal(tz):
for i in range(n):
if stamps[i] == NPY_NAT:
result[i] = NPY_NAT
continue
local_val = tz_convert_utc_to_tzlocal(stamps[i], tz)
dt64_to_dtstruct(local_val, &dts)
result[i] = _normalized_stamp(&dts)
result[i] = _normalize_i8_stamp(local_val)
else:
# Adjust datetime64 timestamp, recompute datetimestruct
trans, deltas, typ = get_dst_info(tz)
Expand All @@ -816,38 +813,36 @@ cpdef ndarray[int64_t] normalize_i8_timestamps(const int64_t[:] stamps, tzinfo t
if stamps[i] == NPY_NAT:
result[i] = NPY_NAT
continue
dt64_to_dtstruct(stamps[i] + delta, &dts)
result[i] = _normalized_stamp(&dts)
local_val = stamps[i] + delta
result[i] = _normalize_i8_stamp(local_val)
else:
pos = trans.searchsorted(stamps, side='right') - 1
for i in range(n):
if stamps[i] == NPY_NAT:
result[i] = NPY_NAT
continue
dt64_to_dtstruct(stamps[i] + deltas[pos[i]], &dts)
result[i] = _normalized_stamp(&dts)
local_val = stamps[i] + deltas[pos[i]]
result[i] = _normalize_i8_stamp(local_val)

return result.base # `.base` to access underlying ndarray


cdef inline int64_t _normalized_stamp(npy_datetimestruct *dts) nogil:
@cython.cdivision
cdef inline int64_t _normalize_i8_stamp(int64_t local_val) nogil:
"""
Normalize the given datetimestruct to midnight, then convert to int64_t.
Round the localized nanosecond timestamp down to the previous midnight.

Parameters
----------
*dts : pointer to npy_datetimestruct
local_val : int64_t

Returns
-------
stamp : int64
"""
dts.hour = 0
dts.min = 0
dts.sec = 0
dts.us = 0
dts.ps = 0
return dtstruct_to_dt64(dts)
int64_t
"""
cdef:
int64_t day_nanos = 24 * 3600 * 1_000_000_000
return local_val - (local_val % day_nanos)


@cython.wraparound(False)
Expand Down