Skip to content

Commit 74e0cde

Browse files
authored
REF: implement tz_localize_to_utc_single (pandas-dev#35108)
* REF: implement tz_localize_to_utc_single * docstring
1 parent d90ca45 commit 74e0cde

File tree

5 files changed

+57
-16
lines changed

5 files changed

+57
-16
lines changed

pandas/_libs/tslib.pyx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ from pandas._libs.tslibs.timezones cimport (
4646
get_dst_info,
4747
is_utc,
4848
is_tzlocal,
49-
utc_pytz as UTC,
5049
)
5150
from pandas._libs.tslibs.conversion cimport (
5251
_TSObject,
@@ -67,8 +66,8 @@ from pandas._libs.tslibs.timestamps cimport create_timestamp_from_ts, _Timestamp
6766
from pandas._libs.tslibs.timestamps import Timestamp
6867

6968
from pandas._libs.tslibs.tzconversion cimport (
70-
tz_convert_single,
7169
tz_convert_utc_to_tzlocal,
70+
tz_localize_to_utc_single,
7271
)
7372

7473
# Note: this is the only non-tslibs intra-pandas dependency here
@@ -250,7 +249,7 @@ def _test_parse_iso8601(ts: str):
250249
check_dts_bounds(&obj.dts)
251250
if out_local == 1:
252251
obj.tzinfo = pytz.FixedOffset(out_tzoffset)
253-
obj.value = tz_convert_single(obj.value, obj.tzinfo, UTC)
252+
obj.value = tz_localize_to_utc_single(obj.value, obj.tzinfo)
254253
return Timestamp(obj.value, tz=obj.tzinfo)
255254
else:
256255
return Timestamp(obj.value)
@@ -708,7 +707,7 @@ cpdef array_to_datetime(
708707
# dateutil.tz.tzoffset objects
709708
out_tzoffset_vals.add(out_tzoffset * 60.)
710709
tz = pytz.FixedOffset(out_tzoffset)
711-
value = tz_convert_single(value, tz, UTC)
710+
value = tz_localize_to_utc_single(value, tz)
712711
out_local = 0
713712
out_tzoffset = 0
714713
else:

pandas/_libs/tslibs/conversion.pyx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,9 @@ from pandas._libs.tslibs.nattype cimport (
3939
c_nat_strings as nat_strings,
4040
)
4141

42-
from pandas._libs.tslibs.tzconversion import tz_localize_to_utc
4342
from pandas._libs.tslibs.tzconversion cimport (
4443
tz_convert_utc_to_tzlocal,
45-
tz_convert_single,
44+
tz_localize_to_utc_single,
4645
)
4746

4847
# ----------------------------------------------------------------------
@@ -481,7 +480,7 @@ cdef _TSObject _create_tsobject_tz_using_offset(npy_datetimestruct dts,
481480
value = dtstruct_to_dt64(&dts)
482481
obj.dts = dts
483482
obj.tzinfo = pytz.FixedOffset(tzoffset)
484-
obj.value = tz_convert_single(value, obj.tzinfo, UTC)
483+
obj.value = tz_localize_to_utc_single(value, obj.tzinfo)
485484
if tz is None:
486485
check_overflows(obj)
487486
return obj
@@ -567,8 +566,8 @@ cdef _TSObject _convert_str_to_tsobject(object ts, tzinfo tz, str unit,
567566
ts = dtstruct_to_dt64(&dts)
568567
if tz is not None:
569568
# shift for _localize_tso
570-
ts = tz_localize_to_utc(np.array([ts], dtype='i8'), tz,
571-
ambiguous='raise')[0]
569+
ts = tz_localize_to_utc_single(ts, tz,
570+
ambiguous="raise")
572571

573572
except OutOfBoundsDatetime:
574573
# GH#19382 for just-barely-OutOfBounds falling back to dateutil

pandas/_libs/tslibs/timestamps.pyx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ from pandas._libs.tslibs.timezones cimport (
5858
is_utc, maybe_get_tz, treat_tz_as_pytz, utc_pytz as UTC,
5959
get_timezone, tz_compare,
6060
)
61-
from pandas._libs.tslibs.tzconversion cimport tz_convert_single
62-
from pandas._libs.tslibs.tzconversion import tz_localize_to_utc
61+
from pandas._libs.tslibs.tzconversion cimport (
62+
tz_convert_single,
63+
tz_localize_to_utc_single,
64+
)
6365

6466
# ----------------------------------------------------------------------
6567
# Constants
@@ -1300,9 +1302,9 @@ default 'raise'
13001302
tz = maybe_get_tz(tz)
13011303
if not isinstance(ambiguous, str):
13021304
ambiguous = [ambiguous]
1303-
value = tz_localize_to_utc(np.array([self.value], dtype='i8'), tz,
1304-
ambiguous=ambiguous,
1305-
nonexistent=nonexistent)[0]
1305+
value = tz_localize_to_utc_single(self.value, tz,
1306+
ambiguous=ambiguous,
1307+
nonexistent=nonexistent)
13061308
return Timestamp(value, tz=tz, freq=self.freq)
13071309
else:
13081310
if tz is None:

pandas/_libs/tslibs/tzconversion.pxd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ from numpy cimport int64_t
44

55
cdef int64_t tz_convert_utc_to_tzlocal(int64_t utc_val, tzinfo tz, bint* fold=*)
66
cpdef int64_t tz_convert_single(int64_t val, tzinfo tz1, tzinfo tz2)
7+
cdef int64_t tz_localize_to_utc_single(
8+
int64_t val, tzinfo tz, object ambiguous=*, object nonexistent=*
9+
) except? -1

pandas/_libs/tslibs/tzconversion.pyx

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,48 @@ from pandas._libs.tslibs.ccalendar cimport DAY_NANOS, HOUR_NANOS
2020
from pandas._libs.tslibs.nattype cimport NPY_NAT
2121
from pandas._libs.tslibs.np_datetime cimport (
2222
npy_datetimestruct, dt64_to_dtstruct)
23-
from pandas._libs.tslibs.timezones cimport get_dst_info, is_tzlocal, is_utc
23+
from pandas._libs.tslibs.timezones cimport (
24+
get_dst_info,
25+
get_utcoffset,
26+
is_fixed_offset,
27+
is_tzlocal,
28+
is_utc,
29+
)
30+
31+
32+
cdef int64_t tz_localize_to_utc_single(
33+
int64_t val, tzinfo tz, object ambiguous=None, object nonexistent=None,
34+
) except? -1:
35+
"""See tz_localize_to_utc.__doc__"""
36+
cdef:
37+
int64_t delta
38+
int64_t[:] deltas
39+
40+
if val == NPY_NAT:
41+
return val
42+
43+
elif is_utc(tz) or tz is None:
44+
return val
45+
46+
elif is_tzlocal(tz):
47+
return _tz_convert_tzlocal_utc(val, tz, to_utc=True)
48+
49+
elif is_fixed_offset(tz):
50+
# TODO: in this case we should be able to use get_utcoffset,
51+
# that returns None for e.g. 'dateutil//usr/share/zoneinfo/Etc/GMT-9'
52+
_, deltas, _ = get_dst_info(tz)
53+
delta = deltas[0]
54+
return val - delta
55+
56+
else:
57+
return tz_localize_to_utc(
58+
np.array([val], dtype="i8"),
59+
tz,
60+
ambiguous=ambiguous,
61+
nonexistent=nonexistent,
62+
)[0]
2463

2564

26-
# TODO: cdef scalar version to call from convert_str_to_tsobject
2765
@cython.boundscheck(False)
2866
@cython.wraparound(False)
2967
def tz_localize_to_utc(ndarray[int64_t] vals, tzinfo tz, object ambiguous=None,

0 commit comments

Comments
 (0)