Skip to content

Commit 59128e3

Browse files
authored
REF: remove always-UTC arg from tz_convert, tz_convert_single (#35154)
1 parent e73d704 commit 59128e3

File tree

11 files changed

+52
-76
lines changed

11 files changed

+52
-76
lines changed

asv_bench/benchmarks/tslibs/tz_convert.py

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
import numpy as np
22
from pytz import UTC
33

4-
from pandas._libs.tslibs.tzconversion import tz_convert, tz_localize_to_utc
4+
from pandas._libs.tslibs.tzconversion import tz_localize_to_utc
55

66
from .tslib import _sizes, _tzs
77

8+
try:
9+
old_sig = False
10+
from pandas._libs.tslibs.tzconversion import tz_convert_from_utc
11+
except ImportError:
12+
old_sig = True
13+
from pandas._libs.tslibs.tzconversion import tz_convert as tz_convert_from_utc
14+
815

916
class TimeTZConvert:
10-
params = (
17+
params = [
1118
_sizes,
1219
[x for x in _tzs if x is not None],
13-
)
20+
]
1421
param_names = ["size", "tz"]
1522

1623
def setup(self, size, tz):
@@ -21,7 +28,13 @@ def time_tz_convert_from_utc(self, size, tz):
2128
# effectively:
2229
# dti = DatetimeIndex(self.i8data, tz=tz)
2330
# dti.tz_localize(None)
24-
tz_convert(self.i8data, UTC, tz)
31+
if size >= 10 ** 6 and str(tz) == "tzlocal()":
32+
# asv fill will because each call takes 8+seconds
33+
return
34+
if old_sig:
35+
tz_convert_from_utc(self.i8data, UTC, tz)
36+
else:
37+
tz_convert_from_utc(self.i8data, tz)
2538

2639
def time_tz_localize_to_utc(self, size, tz):
2740
# effectively:

pandas/_libs/tslibs/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"ints_to_pytimedelta",
2020
"get_resolution",
2121
"Timestamp",
22-
"tz_convert_single",
22+
"tz_convert_from_utc_single",
2323
"to_offset",
2424
"Tick",
2525
"BaseOffset",
@@ -34,7 +34,7 @@
3434
from .resolution import Resolution
3535
from .timedeltas import Timedelta, delta_to_nanoseconds, ints_to_pytimedelta
3636
from .timestamps import Timestamp
37-
from .tzconversion import tz_convert_single
37+
from .tzconversion import tz_convert_from_utc_single
3838
from .vectorized import (
3939
dt64arr_to_periodarr,
4040
get_resolution,

pandas/_libs/tslibs/offsets.pyx

+2-3
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ from pandas._libs.tslibs.np_datetime cimport (
4646
dt64_to_dtstruct,
4747
pydate_to_dtstruct,
4848
)
49-
from pandas._libs.tslibs.timezones cimport utc_pytz as UTC
50-
from pandas._libs.tslibs.tzconversion cimport tz_convert_single
49+
from pandas._libs.tslibs.tzconversion cimport tz_convert_from_utc_single
5150

5251
from .dtypes cimport PeriodDtypeCode
5352
from .timedeltas cimport delta_to_nanoseconds
@@ -264,7 +263,7 @@ cdef _to_dt64D(dt):
264263
# equiv `Timestamp(dt).value` or `dt.timestamp() * 10**9`
265264
nanos = getattr(dt, "nanosecond", 0)
266265
i8 = convert_datetime_to_tsobject(dt, tz=None, nanos=nanos).value
267-
dt = tz_convert_single(i8, UTC, dt.tzinfo)
266+
dt = tz_convert_from_utc_single(i8, dt.tzinfo)
268267
dt = np.int64(dt).astype('datetime64[ns]')
269268
else:
270269
dt = np.datetime64(dt)

pandas/_libs/tslibs/timestamps.pyx

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ from pandas._libs.tslibs.timezones cimport (
5959
get_timezone, tz_compare,
6060
)
6161
from pandas._libs.tslibs.tzconversion cimport (
62-
tz_convert_single,
62+
tz_convert_from_utc_single,
6363
tz_localize_to_utc_single,
6464
)
6565

@@ -1309,7 +1309,7 @@ default 'raise'
13091309
else:
13101310
if tz is None:
13111311
# reset tz
1312-
value = tz_convert_single(self.value, UTC, self.tz)
1312+
value = tz_convert_from_utc_single(self.value, self.tz)
13131313
return Timestamp(value, tz=tz, freq=self.freq)
13141314
else:
13151315
raise TypeError(
@@ -1391,7 +1391,7 @@ default 'raise'
13911391
tzobj = self.tzinfo
13921392
value = self.value
13931393
if tzobj is not None:
1394-
value = tz_convert_single(value, UTC, tzobj)
1394+
value = tz_convert_from_utc_single(value, tzobj)
13951395

13961396
# setup components
13971397
dt64_to_dtstruct(value, &dts)

pandas/_libs/tslibs/tzconversion.pxd

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ from numpy cimport int64_t
33

44

55
cdef int64_t tz_convert_utc_to_tzlocal(int64_t utc_val, tzinfo tz, bint* fold=*)
6-
cpdef int64_t tz_convert_single(int64_t val, tzinfo tz1, tzinfo tz2)
6+
cpdef int64_t tz_convert_from_utc_single(int64_t val, tzinfo tz)
77
cdef int64_t tz_localize_to_utc_single(
88
int64_t val, tzinfo tz, object ambiguous=*, object nonexistent=*
99
) except? -1

pandas/_libs/tslibs/tzconversion.pyx

+17-51
Original file line numberDiff line numberDiff line change
@@ -366,93 +366,69 @@ cdef int64_t tz_convert_utc_to_tzlocal(int64_t utc_val, tzinfo tz, bint* fold=NU
366366
return _tz_convert_tzlocal_utc(utc_val, tz, to_utc=False, fold=fold)
367367

368368

369-
cpdef int64_t tz_convert_single(int64_t val, tzinfo tz1, tzinfo tz2):
369+
cpdef int64_t tz_convert_from_utc_single(int64_t val, tzinfo tz):
370370
"""
371-
Convert the val (in i8) from timezone1 to timezone2
371+
Convert the val (in i8) from UTC to tz
372372
373-
This is a single timezone version of tz_convert
373+
This is a single value version of tz_convert_from_utc.
374374
375375
Parameters
376376
----------
377377
val : int64
378-
tz1 : tzinfo
379-
tz2 : tzinfo
378+
tz : tzinfo
380379
381380
Returns
382381
-------
383382
converted: int64
384383
"""
385384
cdef:
386385
int64_t arr[1]
387-
bint to_utc = is_utc(tz2)
388-
tzinfo tz
389-
390-
# See GH#17734 We should always be converting either from UTC or to UTC
391-
assert is_utc(tz1) or to_utc
392386

393387
if val == NPY_NAT:
394388
return val
395389

396-
if to_utc:
397-
tz = tz1
398-
else:
399-
tz = tz2
400-
401390
if is_utc(tz):
402391
return val
403392
elif is_tzlocal(tz):
404-
return _tz_convert_tzlocal_utc(val, tz, to_utc=to_utc)
393+
return _tz_convert_tzlocal_utc(val, tz, to_utc=False)
405394
else:
406395
arr[0] = val
407-
return _tz_convert_dst(arr, tz, to_utc=to_utc)[0]
396+
return _tz_convert_dst(arr, tz)[0]
408397

409398

410-
def tz_convert(int64_t[:] vals, tzinfo tz1, tzinfo tz2):
399+
def tz_convert_from_utc(int64_t[:] vals, tzinfo tz):
411400
"""
412-
Convert the values (in i8) from timezone1 to timezone2
401+
Convert the values (in i8) from UTC to tz
413402
414403
Parameters
415404
----------
416405
vals : int64 ndarray
417-
tz1 : tzinfo
418-
tz2 : tzinfo
406+
tz : tzinfo
419407
420408
Returns
421409
-------
422410
int64 ndarray of converted
423411
"""
424412
cdef:
425413
int64_t[:] converted
426-
bint to_utc = is_utc(tz2)
427-
tzinfo tz
428-
429-
# See GH#17734 We should always be converting from UTC; otherwise
430-
# should use tz_localize_to_utc.
431-
assert is_utc(tz1)
432414

433415
if len(vals) == 0:
434416
return np.array([], dtype=np.int64)
435417

436-
if to_utc:
437-
tz = tz1
438-
else:
439-
tz = tz2
440-
441-
converted = _tz_convert_one_way(vals, tz, to_utc=to_utc)
418+
converted = _tz_convert_from_utc(vals, tz)
442419
return np.array(converted, dtype=np.int64)
443420

444421

445422
@cython.boundscheck(False)
446423
@cython.wraparound(False)
447-
cdef int64_t[:] _tz_convert_one_way(int64_t[:] vals, tzinfo tz, bint to_utc):
424+
cdef int64_t[:] _tz_convert_from_utc(int64_t[:] vals, tzinfo tz):
448425
"""
449426
Convert the given values (in i8) either to UTC or from UTC.
450427
451428
Parameters
452429
----------
453430
vals : int64 ndarray
454-
tz1 : tzinfo
455-
to_utc : bool
431+
tz : tzinfo
456432
457433
Returns
458434
-------
@@ -472,9 +448,9 @@ cdef int64_t[:] _tz_convert_one_way(int64_t[:] vals, tzinfo tz, bint to_utc):
472448
if val == NPY_NAT:
473449
converted[i] = NPY_NAT
474450
else:
475-
converted[i] = _tz_convert_tzlocal_utc(val, tz, to_utc)
451+
converted[i] = _tz_convert_tzlocal_utc(val, tz, to_utc=False)
476452
else:
477-
converted = _tz_convert_dst(vals, tz, to_utc)
453+
converted = _tz_convert_dst(vals, tz)
478454

479455
return converted
480456

@@ -565,9 +541,7 @@ cdef int64_t _tz_convert_tzlocal_utc(int64_t val, tzinfo tz, bint to_utc=True,
565541

566542
@cython.boundscheck(False)
567543
@cython.wraparound(False)
568-
cdef int64_t[:] _tz_convert_dst(
569-
const int64_t[:] values, tzinfo tz, bint to_utc=True,
570-
):
544+
cdef int64_t[:] _tz_convert_dst(const int64_t[:] values, tzinfo tz):
571545
"""
572546
tz_convert for non-UTC non-tzlocal cases where we have to check
573547
DST transitions pointwise.
@@ -576,8 +550,6 @@ cdef int64_t[:] _tz_convert_dst(
576550
----------
577551
values : ndarray[int64_t]
578552
tz : tzinfo
579-
to_utc : bool
580-
True if converting _to_ UTC, False if converting _from_ utc
581553
582554
Returns
583555
-------
@@ -607,10 +579,7 @@ cdef int64_t[:] _tz_convert_dst(
607579
if v == NPY_NAT:
608580
result[i] = v
609581
else:
610-
if to_utc:
611-
result[i] = v - delta
612-
else:
613-
result[i] = v + delta
582+
result[i] = v + delta
614583

615584
else:
616585
# Previously, this search was done pointwise to try and benefit
@@ -629,9 +598,6 @@ cdef int64_t[:] _tz_convert_dst(
629598
# it elsewhere?
630599
raise ValueError("First time before start of DST info")
631600

632-
if to_utc:
633-
result[i] = v - deltas[pos[i]]
634-
else:
635-
result[i] = v + deltas[pos[i]]
601+
result[i] = v + deltas[pos[i]]
636602

637603
return result

pandas/core/arrays/datetimes.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ def _local_timestamps(self):
728728
This is used to calculate time-of-day information as if the timestamps
729729
were timezone-naive.
730730
"""
731-
return tzconversion.tz_convert(self.asi8, timezones.UTC, self.tz)
731+
return tzconversion.tz_convert_from_utc(self.asi8, self.tz)
732732

733733
def tz_convert(self, tz):
734734
"""
@@ -960,7 +960,7 @@ def tz_localize(self, tz, ambiguous="raise", nonexistent="raise"):
960960

961961
if self.tz is not None:
962962
if tz is None:
963-
new_dates = tzconversion.tz_convert(self.asi8, timezones.UTC, self.tz)
963+
new_dates = tzconversion.tz_convert_from_utc(self.asi8, self.tz)
964964
else:
965965
raise TypeError("Already tz-aware, use tz_convert to convert.")
966966
else:

pandas/tests/scalar/timestamp/test_timezones.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ def test_timestamp_to_datetime_tzoffset(self):
334334
def test_timestamp_constructor_near_dst_boundary(self):
335335
# GH#11481 & GH#15777
336336
# Naive string timestamps were being localized incorrectly
337-
# with tz_convert_single instead of tz_localize_to_utc
337+
# with tz_convert_from_utc_single instead of tz_localize_to_utc
338338

339339
for tz in ["Europe/Brussels", "Europe/Prague"]:
340340
result = Timestamp("2015-10-25 01:00", tz=tz)

pandas/tests/tslibs/test_api.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def test_namespace():
4747
"delta_to_nanoseconds",
4848
"ints_to_pytimedelta",
4949
"localize_pydatetime",
50-
"tz_convert_single",
50+
"tz_convert_from_utc_single",
5151
"to_offset",
5252
]
5353

pandas/tests/tslibs/test_conversion.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,16 @@
1212

1313
def _compare_utc_to_local(tz_didx):
1414
def f(x):
15-
return tzconversion.tz_convert_single(x, UTC, tz_didx.tz)
15+
return tzconversion.tz_convert_from_utc_single(x, tz_didx.tz)
1616

17-
result = tzconversion.tz_convert(tz_didx.asi8, UTC, tz_didx.tz)
17+
result = tzconversion.tz_convert_from_utc(tz_didx.asi8, tz_didx.tz)
1818
expected = np.vectorize(f)(tz_didx.asi8)
1919

2020
tm.assert_numpy_array_equal(result, expected)
2121

2222

2323
def _compare_local_to_utc(tz_didx, naive_didx):
2424
# Check that tz_localize behaves the same vectorized and pointwise.
25-
def f(x):
26-
return tzconversion.tz_convert_single(x, tz_didx.tz, UTC)
27-
2825
err1 = err2 = None
2926
try:
3027
result = tzconversion.tz_localize_to_utc(naive_didx.asi8, tz_didx.tz)
@@ -71,7 +68,7 @@ def test_tz_convert_single_matches_tz_convert(tz_aware_fixture, freq):
7168
],
7269
)
7370
def test_tz_convert_corner(arr):
74-
result = tzconversion.tz_convert(arr, UTC, timezones.maybe_get_tz("Asia/Tokyo"))
71+
result = tzconversion.tz_convert_from_utc(arr, timezones.maybe_get_tz("Asia/Tokyo"))
7572
tm.assert_numpy_array_equal(result, arr)
7673

7774

pandas/tseries/frequencies.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
)
2222
from pandas._libs.tslibs.parsing import get_rule_month
2323
from pandas._libs.tslibs.resolution import month_position_check
24-
from pandas._libs.tslibs.timezones import UTC
2524
from pandas.util._decorators import cache_readonly
2625

2726
from pandas.core.dtypes.common import (
@@ -198,7 +197,9 @@ def __init__(self, index, warn: bool = True):
198197
# the timezone so they are in local time
199198
if hasattr(index, "tz"):
200199
if index.tz is not None:
201-
self.i8values = tzconversion.tz_convert(self.i8values, UTC, index.tz)
200+
self.i8values = tzconversion.tz_convert_from_utc(
201+
self.i8values, index.tz
202+
)
202203

203204
self.warn = warn
204205

0 commit comments

Comments
 (0)