Skip to content

CLN: rename _tz_localize_using_tzinfo_api, standardize patterns #46434

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
Mar 19, 2022
Merged
Show file tree
Hide file tree
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
6 changes: 3 additions & 3 deletions pandas/_libs/tslibs/conversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ from pandas._libs.tslibs.nattype cimport (
)
from pandas._libs.tslibs.tzconversion cimport (
bisect_right_i8,
tz_convert_utc_to_tzlocal,
localize_tzinfo_api,
tz_localize_to_utc_single,
)

Expand Down Expand Up @@ -556,7 +556,7 @@ cdef _TSObject _create_tsobject_tz_using_offset(npy_datetimestruct dts,
if is_utc(tz):
pass
elif is_tzlocal(tz):
tz_convert_utc_to_tzlocal(obj.value, tz, &obj.fold)
localize_tzinfo_api(obj.value, tz, &obj.fold)
else:
trans, deltas, typ = get_dst_info(tz)

Expand Down Expand Up @@ -725,7 +725,7 @@ cdef inline void _localize_tso(_TSObject obj, tzinfo tz):
elif obj.value == NPY_NAT:
pass
elif is_tzlocal(tz):
local_val = tz_convert_utc_to_tzlocal(obj.value, tz, &obj.fold)
local_val = obj.value + localize_tzinfo_api(obj.value, tz, &obj.fold)
dt64_to_dtstruct(local_val, &obj.dts)
else:
# Adjust datetime64 timestamp, recompute datetimestruct
Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/tzconversion.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ from cpython.datetime cimport tzinfo
from numpy cimport int64_t


cdef int64_t tz_convert_utc_to_tzlocal(
cdef int64_t localize_tzinfo_api(
int64_t utc_val, tzinfo tz, bint* fold=*
) except? -1
cpdef int64_t tz_convert_from_utc_single(int64_t val, tzinfo tz)
Expand Down
112 changes: 59 additions & 53 deletions pandas/_libs/tslibs/tzconversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ from cython import Py_ssize_t
from cpython.datetime cimport (
PyDelta_Check,
datetime,
datetime_new,
import_datetime,
timedelta,
tzinfo,
Expand Down Expand Up @@ -43,6 +44,7 @@ from pandas._libs.tslibs.timezones cimport (
is_fixed_offset,
is_tzlocal,
is_utc,
utc_pytz,
)


Expand All @@ -61,7 +63,7 @@ cdef int64_t tz_localize_to_utc_single(
return val

elif is_tzlocal(tz):
return _tz_convert_tzlocal_utc(val, tz, to_utc=True)
return val - _tz_localize_using_tzinfo_api(val, tz, to_utc=True)

elif is_fixed_offset(tz):
# TODO: in this case we should be able to use get_utcoffset,
Expand Down Expand Up @@ -142,7 +144,7 @@ timedelta-like}
if v == NPY_NAT:
result[i] = NPY_NAT
else:
result[i] = _tz_convert_tzlocal_utc(v, tz, to_utc=True)
result[i] = v - _tz_localize_using_tzinfo_api(v, tz, to_utc=True)
return result

# silence false-positive compiler warning
Expand Down Expand Up @@ -402,7 +404,7 @@ cdef ndarray[int64_t] _get_dst_hours(
# ----------------------------------------------------------------------
# Timezone Conversion

cdef int64_t tz_convert_utc_to_tzlocal(
cdef int64_t localize_tzinfo_api(
int64_t utc_val, tzinfo tz, bint* fold=NULL
) except? -1:
"""
Expand All @@ -416,20 +418,21 @@ cdef int64_t tz_convert_utc_to_tzlocal(

Returns
-------
local_val : int64_t
delta : int64_t
Value to add when converting from utc.
"""
return _tz_convert_tzlocal_utc(utc_val, tz, to_utc=False, fold=fold)
return _tz_localize_using_tzinfo_api(utc_val, tz, to_utc=False, fold=fold)


cpdef int64_t tz_convert_from_utc_single(int64_t val, tzinfo tz):
cpdef int64_t tz_convert_from_utc_single(int64_t utc_val, tzinfo tz):
"""
Convert the val (in i8) from UTC to tz

This is a single value version of tz_convert_from_utc.

Parameters
----------
val : int64
utc_val : int64
tz : tzinfo

Returns
Expand All @@ -443,22 +446,22 @@ cpdef int64_t tz_convert_from_utc_single(int64_t val, tzinfo tz):
int64_t* tdata
intp_t pos

if val == NPY_NAT:
return val
if utc_val == NPY_NAT:
return utc_val

if is_utc(tz):
return val
return utc_val
elif is_tzlocal(tz):
return _tz_convert_tzlocal_utc(val, tz, to_utc=False)
return utc_val + _tz_localize_using_tzinfo_api(utc_val, tz, to_utc=False)
elif is_fixed_offset(tz):
_, deltas, _ = get_dst_info(tz)
delta = deltas[0]
return val + delta
return utc_val + delta
else:
trans, deltas, _ = get_dst_info(tz)
tdata = <int64_t*>cnp.PyArray_DATA(trans)
pos = bisect_right_i8(tdata, val, trans.shape[0]) - 1
return val + deltas[pos]
pos = bisect_right_i8(tdata, utc_val, trans.shape[0]) - 1
return utc_val + deltas[pos]


def tz_convert_from_utc(const int64_t[:] vals, tzinfo tz):
Expand Down Expand Up @@ -486,32 +489,34 @@ def tz_convert_from_utc(const int64_t[:] vals, tzinfo tz):

@cython.boundscheck(False)
@cython.wraparound(False)
cdef const int64_t[:] _tz_convert_from_utc(const int64_t[:] vals, tzinfo tz):
cdef const int64_t[:] _tz_convert_from_utc(const int64_t[:] stamps, tzinfo tz):
"""
Convert the given values (in i8) either to UTC or from UTC.

Parameters
----------
vals : int64 ndarray
stamps : int64 ndarray
tz : tzinfo

Returns
-------
converted : ndarray[int64_t]
"""
cdef:
int64_t[::1] converted, deltas
Py_ssize_t i, ntrans = -1, n = vals.shape[0]
int64_t val, delta = 0 # avoid not-initialized-warning
intp_t pos
Py_ssize_t i, ntrans = -1, n = stamps.shape[0]
ndarray[int64_t] trans
int64_t[::1] deltas
int64_t* tdata = NULL
intp_t pos
int64_t utc_val, local_val, delta = NPY_NAT
bint use_utc = False, use_tzlocal = False, use_fixed = False
str typ
bint use_tzlocal = False, use_fixed = False, use_utc = True

int64_t[::1] result

if is_utc(tz):
# Much faster than going through the "standard" pattern below
return vals.copy()
return stamps.copy()

if is_utc(tz) or tz is None:
use_utc = True
Expand All @@ -520,59 +525,62 @@ cdef const int64_t[:] _tz_convert_from_utc(const int64_t[:] vals, tzinfo tz):
else:
trans, deltas, typ = get_dst_info(tz)
ntrans = trans.shape[0]

if typ not in ["pytz", "dateutil"]:
# FixedOffset, we know len(deltas) == 1
delta = deltas[0]
# static/fixed; in this case we know that len(delta) == 1
use_fixed = True
delta = deltas[0]
else:
tdata = <int64_t*>cnp.PyArray_DATA(trans)

converted = np.empty(n, dtype=np.int64)
result = np.empty(n, dtype=np.int64)

for i in range(n):
val = vals[i]
if val == NPY_NAT:
converted[i] = NPY_NAT
utc_val = stamps[i]
if utc_val == NPY_NAT:
result[i] = NPY_NAT
continue

# The pattern used in vectorized.pyx checks for use_utc here,
# but we handle that case above.
if use_tzlocal:
converted[i] = _tz_convert_tzlocal_utc(val, tz, to_utc=False)
local_val = utc_val + _tz_localize_using_tzinfo_api(utc_val, tz, to_utc=False)
elif use_fixed:
converted[i] = val + delta
local_val = utc_val + delta
else:
pos = bisect_right_i8(tdata, val, ntrans) - 1
converted[i] = val + deltas[pos]
pos = bisect_right_i8(tdata, utc_val, ntrans) - 1
local_val = utc_val + deltas[pos]

result[i] = local_val

return converted
return result


# OSError may be thrown by tzlocal on windows at or close to 1970-01-01
# see https://github.com/pandas-dev/pandas/pull/37591#issuecomment-720628241
cdef int64_t _tz_convert_tzlocal_utc(int64_t val, tzinfo tz, bint to_utc=True,
bint* fold=NULL) except? -1:
cdef int64_t _tz_localize_using_tzinfo_api(
int64_t val, tzinfo tz, bint to_utc=True, bint* fold=NULL
) except? -1:
"""
Convert the i8 representation of a datetime from a tzlocal timezone to
UTC, or vice-versa.
Convert the i8 representation of a datetime from a general-cast timezone to
UTC, or vice-versa using the datetime/tzinfo API.

Private, not intended for use outside of tslibs.conversion
Private, not intended for use outside of tslibs.tzconversion.

Parameters
----------
val : int64_t
tz : tzinfo
to_utc : bint
True if converting tzlocal _to_ UTC, False if going the other direction
True if converting _to_ UTC, False if going the other direction.
fold : bint*, default NULL
pointer to fold: whether datetime ends up in a fold or not
after adjustment
after adjustment.
Only passed with to_utc=False.

Returns
-------
result : int64_t
delta : int64_t
Value to add when converting from utc, subtract when converting to utc.

Notes
-----
Expand All @@ -586,23 +594,21 @@ cdef int64_t _tz_convert_tzlocal_utc(int64_t val, tzinfo tz, bint to_utc=True,

dt64_to_dtstruct(val, &dts)

dt = datetime(dts.year, dts.month, dts.day, dts.hour,
dts.min, dts.sec, dts.us)

# tz.utcoffset only makes sense if datetime
# is _wall time_, so if val is a UTC timestamp convert to wall time
# datetime_new is cython-optimized constructor
if not to_utc:
dt = dt.replace(tzinfo=tzutc())
# tz.utcoffset only makes sense if datetime
# is _wall time_, so if val is a UTC timestamp convert to wall time
dt = datetime_new(dts.year, dts.month, dts.day, dts.hour,
dts.min, dts.sec, dts.us, utc_pytz)
dt = dt.astimezone(tz)

if fold is not NULL:
# NB: fold is only passed with to_utc=False
fold[0] = dt.fold
else:
dt = datetime_new(dts.year, dts.month, dts.day, dts.hour,
dts.min, dts.sec, dts.us, None)

td = tz.utcoffset(dt)
delta = int(td.total_seconds() * 1_000_000_000)

if to_utc:
return val - delta
else:
return val + delta
return delta
Loading