Skip to content

REF: remove always-UTC arg from tz_convert, tz_convert_single #35154

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 28 commits into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
30c4348
REF: standardize tz_convert_single usage
jbrockmendel Jul 2, 2020
02517fc
CLN: tz_convert is always from UTC
jbrockmendel Jul 2, 2020
830c4bd
PERF: avoid copy in tz_convert dst cases
jbrockmendel Jul 2, 2020
6bc6570
ASVs
jbrockmendel Jul 3, 2020
7f7350b
asv fixup
jbrockmendel Jul 3, 2020
92cada7
REF: implement tz_localize_to_utc_single
jbrockmendel Jul 3, 2020
6e9afd7
docstring
jbrockmendel Jul 3, 2020
617ab79
DOC: Fix code formatting and typos in Series.tz_localize (#35110)
StefRe Jul 3, 2020
9b39dbf
PERF: Fix quantile perf regression (#35101)
TomAugspurger Jul 3, 2020
7a9d5cc
CLN: convert lambda to function (#35117)
topper-123 Jul 4, 2020
55be9e9
REF: dont consolidate in BlockManager.equals (#34962)
jbrockmendel Jul 6, 2020
b389653
CI: pin isort version (#35136)
AlexKirko Jul 6, 2020
c4309b6
CI: pin sphinx <= 3.1.1 for autodoc failure (#35139)
jorisvandenbossche Jul 6, 2020
e1507dd
Fix numpy warning (#35085)
TomAugspurger Jul 6, 2020
8b06a50
TYP: type unit as str (#35099)
jbrockmendel Jul 6, 2020
5fc5bc6
CLN: never to_utc
jbrockmendel Jul 6, 2020
e25e292
Merge branch 'master' of https://github.com/pandas-dev/pandas into re…
jbrockmendel Jul 7, 2020
865344f
CLN: remove always-UTC arg from tz_convert, tz_convert_single
jbrockmendel Jul 7, 2020
6c17135
fix docstring
jbrockmendel Jul 7, 2020
4110fb3
Merge branch 'master' of https://github.com/pandas-dev/pandas into re…
jbrockmendel Jul 7, 2020
c197d03
Merge branch 'master' of https://github.com/pandas-dev/pandas into re…
jbrockmendel Jul 8, 2020
1855e7f
rename
jbrockmendel Jul 8, 2020
b928b54
rename typo fixup
jbrockmendel Jul 8, 2020
4305c90
update import
jbrockmendel Jul 8, 2020
37a5796
asv backcompat
jbrockmendel Jul 8, 2020
4757798
dummy to force CI
jbrockmendel Jul 8, 2020
6399998
Merge branch 'master' of https://github.com/pandas-dev/pandas into re…
jbrockmendel Jul 8, 2020
99e29af
update benchmark
jbrockmendel Jul 9, 2020
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
3 changes: 1 addition & 2 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ from pandas._libs.tslibs.np_datetime cimport (
dt64_to_dtstruct,
pydate_to_dtstruct,
)
from pandas._libs.tslibs.timezones cimport utc_pytz as UTC
from pandas._libs.tslibs.tzconversion cimport tz_convert_single

from .dtypes cimport PeriodDtypeCode
Expand Down Expand Up @@ -263,7 +262,7 @@ cdef _to_dt64D(dt):
# equiv `Timestamp(dt).value` or `dt.timestamp() * 10**9`
nanos = getattr(dt, "nanosecond", 0)
i8 = convert_datetime_to_tsobject(dt, tz=None, nanos=nanos).value
dt = tz_convert_single(i8, UTC, dt.tzinfo)
dt = tz_convert_single(i8, dt.tzinfo)
dt = np.int64(dt).astype('datetime64[ns]')
else:
dt = np.datetime64(dt)
Expand Down
4 changes: 2 additions & 2 deletions pandas/_libs/tslibs/timestamps.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1309,7 +1309,7 @@ default 'raise'
else:
if tz is None:
# reset tz
value = tz_convert_single(self.value, UTC, self.tz)
value = tz_convert_single(self.value, self.tz)
return Timestamp(value, tz=tz, freq=self.freq)
else:
raise TypeError(
Expand Down Expand Up @@ -1391,7 +1391,7 @@ default 'raise'
tzobj = self.tzinfo
value = self.value
if tzobj is not None:
value = tz_convert_single(value, UTC, tzobj)
value = tz_convert_single(value, tzobj)

# setup components
dt64_to_dtstruct(value, &dts)
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 @@ -3,7 +3,7 @@ from numpy cimport int64_t


cdef int64_t tz_convert_utc_to_tzlocal(int64_t utc_val, tzinfo tz, bint* fold=*)
cpdef int64_t tz_convert_single(int64_t val, tzinfo tz1, tzinfo tz2)
cpdef int64_t tz_convert_single(int64_t val, tzinfo tz)
cdef int64_t tz_localize_to_utc_single(
int64_t val, tzinfo tz, object ambiguous=*, object nonexistent=*
) except? -1
66 changes: 16 additions & 50 deletions pandas/_libs/tslibs/tzconversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -366,93 +366,69 @@ cdef int64_t tz_convert_utc_to_tzlocal(int64_t utc_val, tzinfo tz, bint* fold=NU
return _tz_convert_tzlocal_utc(utc_val, tz, to_utc=False, fold=fold)


cpdef int64_t tz_convert_single(int64_t val, tzinfo tz1, tzinfo tz2):
cpdef int64_t tz_convert_single(int64_t val, tzinfo tz):
"""
Convert the val (in i8) from timezone1 to timezone2
Convert the val (in i8) from UTC to tz

This is a single timezone version of tz_convert
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this still required?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated


Parameters
----------
val : int64
tz1 : tzinfo
tz2 : tzinfo
tz : tzinfo

Returns
-------
converted: int64
"""
cdef:
int64_t arr[1]
bint to_utc = is_utc(tz2)
tzinfo tz

# See GH#17734 We should always be converting either from UTC or to UTC
assert is_utc(tz1) or to_utc

if val == NPY_NAT:
return val

if to_utc:
tz = tz1
else:
tz = tz2

if is_utc(tz):
return val
elif is_tzlocal(tz):
return _tz_convert_tzlocal_utc(val, tz, to_utc=to_utc)
return _tz_convert_tzlocal_utc(val, tz, to_utc=False)
else:
arr[0] = val
return _tz_convert_dst(arr, tz, to_utc=to_utc)[0]
return _tz_convert_dst(arr, tz)[0]


def tz_convert(int64_t[:] vals, tzinfo tz1, tzinfo tz2):
def tz_convert(int64_t[:] vals, tzinfo tz):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we rename this tz_convert_from_utc to make the intention clear?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure i guess

"""
Convert the values (in i8) from timezone1 to timezone2
Convert the values (in i8) from UTC to tz

Parameters
----------
vals : int64 ndarray
tz1 : tzinfo
tz2 : tzinfo
tz : tzinfo

Returns
-------
int64 ndarray of converted
"""
cdef:
int64_t[:] converted
bint to_utc = is_utc(tz2)
tzinfo tz

# See GH#17734 We should always be converting from UTC; otherwise
# should use tz_localize_to_utc.
assert is_utc(tz1)

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

if to_utc:
tz = tz1
else:
tz = tz2

converted = _tz_convert_one_way(vals, tz, to_utc=to_utc)
converted = _tz_convert_one_way(vals, tz)
return np.array(converted, dtype=np.int64)


@cython.boundscheck(False)
@cython.wraparound(False)
cdef int64_t[:] _tz_convert_one_way(int64_t[:] vals, tzinfo tz, bint to_utc):
cdef int64_t[:] _tz_convert_one_way(int64_t[:] vals, tzinfo tz):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's rename this too

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated+green

"""
Convert the given values (in i8) either to UTC or from UTC.

Parameters
----------
vals : int64 ndarray
tz1 : tzinfo
to_utc : bool
tz : tzinfo

Returns
-------
Expand All @@ -472,9 +448,9 @@ cdef int64_t[:] _tz_convert_one_way(int64_t[:] vals, tzinfo tz, bint to_utc):
if val == NPY_NAT:
converted[i] = NPY_NAT
else:
converted[i] = _tz_convert_tzlocal_utc(val, tz, to_utc)
converted[i] = _tz_convert_tzlocal_utc(val, tz, to_utc=False)
else:
converted = _tz_convert_dst(vals, tz, to_utc)
converted = _tz_convert_dst(vals, tz)

return converted

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

@cython.boundscheck(False)
@cython.wraparound(False)
cdef int64_t[:] _tz_convert_dst(
const int64_t[:] values, tzinfo tz, bint to_utc=True,
):
cdef int64_t[:] _tz_convert_dst(const int64_t[:] values, tzinfo tz):
"""
tz_convert for non-UTC non-tzlocal cases where we have to check
DST transitions pointwise.
Expand All @@ -576,8 +550,6 @@ cdef int64_t[:] _tz_convert_dst(
----------
values : ndarray[int64_t]
tz : tzinfo
to_utc : bool
True if converting _to_ UTC, False if converting _from_ utc

Returns
-------
Expand Down Expand Up @@ -607,10 +579,7 @@ cdef int64_t[:] _tz_convert_dst(
if v == NPY_NAT:
result[i] = v
else:
if to_utc:
result[i] = v - delta
else:
result[i] = v + delta
result[i] = v + delta

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

if to_utc:
result[i] = v - deltas[pos[i]]
else:
result[i] = v + deltas[pos[i]]
result[i] = v + deltas[pos[i]]

return result
4 changes: 2 additions & 2 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ def _local_timestamps(self):
This is used to calculate time-of-day information as if the timestamps
were timezone-naive.
"""
return tzconversion.tz_convert(self.asi8, timezones.UTC, self.tz)
return tzconversion.tz_convert(self.asi8, self.tz)

def tz_convert(self, tz):
"""
Expand Down Expand Up @@ -956,7 +956,7 @@ def tz_localize(self, tz, ambiguous="raise", nonexistent="raise"):

if self.tz is not None:
if tz is None:
new_dates = tzconversion.tz_convert(self.asi8, timezones.UTC, self.tz)
new_dates = tzconversion.tz_convert(self.asi8, self.tz)
else:
raise TypeError("Already tz-aware, use tz_convert to convert.")
else:
Expand Down
9 changes: 3 additions & 6 deletions pandas/tests/tslibs/test_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,16 @@

def _compare_utc_to_local(tz_didx):
def f(x):
return tzconversion.tz_convert_single(x, UTC, tz_didx.tz)
return tzconversion.tz_convert_single(x, tz_didx.tz)

result = tzconversion.tz_convert(tz_didx.asi8, UTC, tz_didx.tz)
result = tzconversion.tz_convert(tz_didx.asi8, tz_didx.tz)
expected = np.vectorize(f)(tz_didx.asi8)

tm.assert_numpy_array_equal(result, expected)


def _compare_local_to_utc(tz_didx, naive_didx):
# Check that tz_localize behaves the same vectorized and pointwise.
def f(x):
return tzconversion.tz_convert_single(x, tz_didx.tz, UTC)

err1 = err2 = None
try:
result = tzconversion.tz_localize_to_utc(naive_didx.asi8, tz_didx.tz)
Expand Down Expand Up @@ -71,7 +68,7 @@ def test_tz_convert_single_matches_tz_convert(tz_aware_fixture, freq):
],
)
def test_tz_convert_corner(arr):
result = tzconversion.tz_convert(arr, UTC, timezones.maybe_get_tz("Asia/Tokyo"))
result = tzconversion.tz_convert(arr, timezones.maybe_get_tz("Asia/Tokyo"))
tm.assert_numpy_array_equal(result, arr)


Expand Down
3 changes: 1 addition & 2 deletions pandas/tseries/frequencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
)
from pandas._libs.tslibs.parsing import get_rule_month
from pandas._libs.tslibs.resolution import month_position_check
from pandas._libs.tslibs.timezones import UTC
from pandas.util._decorators import cache_readonly

from pandas.core.dtypes.common import (
Expand Down Expand Up @@ -198,7 +197,7 @@ def __init__(self, index, warn: bool = True):
# the timezone so they are in local time
if hasattr(index, "tz"):
if index.tz is not None:
self.i8values = tzconversion.tz_convert(self.i8values, UTC, index.tz)
self.i8values = tzconversion.tz_convert(self.i8values, index.tz)

self.warn = warn

Expand Down