Skip to content

Commit 3836f87

Browse files
jbrockmendelyehoshuadimarsky
authored andcommitted
REF: _infer_tsobject_fold to infer_datetuil_fold (pandas-dev#46516)
1 parent ad1cd6f commit 3836f87

File tree

7 files changed

+85
-73
lines changed

7 files changed

+85
-73
lines changed

pandas/_libs/tslibs/conversion.pxd

-2
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,3 @@ cdef int64_t get_datetime64_nanos(object val) except? -1
3131
cpdef datetime localize_pydatetime(datetime dt, tzinfo tz)
3232
cdef int64_t cast_from_unit(object ts, str unit) except? -1
3333
cpdef (int64_t, int) precision_from_unit(str unit)
34-
35-
cdef int64_t normalize_i8_stamp(int64_t local_val) nogil

pandas/_libs/tslibs/conversion.pyx

+3-66
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ from pandas._libs.tslibs.nattype cimport (
7272
)
7373
from pandas._libs.tslibs.tzconversion cimport (
7474
bisect_right_i8,
75+
infer_datetuil_fold,
7576
localize_tzinfo_api,
7677
tz_localize_to_utc_single,
7778
)
@@ -530,7 +531,7 @@ cdef _TSObject _create_tsobject_tz_using_offset(npy_datetimestruct dts,
530531
if typ == 'dateutil':
531532
tdata = <int64_t*>cnp.PyArray_DATA(trans)
532533
pos = bisect_right_i8(tdata, obj.value, trans.shape[0]) - 1
533-
obj.fold = _infer_tsobject_fold(obj, trans, deltas, pos)
534+
obj.fold = infer_datetuil_fold(obj.value, trans, deltas, pos)
534535

535536
# Keep the converter same as PyDateTime's
536537
dt = datetime(obj.dts.year, obj.dts.month, obj.dts.day,
@@ -714,7 +715,7 @@ cdef inline void _localize_tso(_TSObject obj, tzinfo tz):
714715
local_val = obj.value + deltas[pos]
715716

716717
# dateutil supports fold, so we infer fold from value
717-
obj.fold = _infer_tsobject_fold(obj, trans, deltas, pos)
718+
obj.fold = infer_datetuil_fold(obj.value, trans, deltas, pos)
718719
else:
719720
# All other cases have len(deltas) == 1. As of 2018-07-17
720721
# (and 2022-03-07), all test cases that get here have
@@ -726,49 +727,6 @@ cdef inline void _localize_tso(_TSObject obj, tzinfo tz):
726727
obj.tzinfo = tz
727728

728729

729-
cdef inline bint _infer_tsobject_fold(
730-
_TSObject obj,
731-
const int64_t[:] trans,
732-
const int64_t[:] deltas,
733-
intp_t pos,
734-
):
735-
"""
736-
Infer _TSObject fold property from value by assuming 0 and then setting
737-
to 1 if necessary.
738-
739-
Parameters
740-
----------
741-
obj : _TSObject
742-
trans : ndarray[int64_t]
743-
ndarray of offset transition points in nanoseconds since epoch.
744-
deltas : int64_t[:]
745-
array of offsets corresponding to transition points in trans.
746-
pos : intp_t
747-
Position of the last transition point before taking fold into account.
748-
749-
Returns
750-
-------
751-
bint
752-
Due to daylight saving time, one wall clock time can occur twice
753-
when shifting from summer to winter time; fold describes whether the
754-
datetime-like corresponds to the first (0) or the second time (1)
755-
the wall clock hits the ambiguous time
756-
757-
References
758-
----------
759-
.. [1] "PEP 495 - Local Time Disambiguation"
760-
https://www.python.org/dev/peps/pep-0495/#the-fold-attribute
761-
"""
762-
cdef:
763-
bint fold = 0
764-
765-
if pos > 0:
766-
fold_delta = deltas[pos - 1] - deltas[pos]
767-
if obj.value - fold_delta < trans[pos]:
768-
fold = 1
769-
770-
return fold
771-
772730
cdef inline datetime _localize_pydatetime(datetime dt, tzinfo tz):
773731
"""
774732
Take a datetime/Timestamp in UTC and localizes to timezone tz.
@@ -802,24 +760,3 @@ cpdef inline datetime localize_pydatetime(datetime dt, tzinfo tz):
802760
elif isinstance(dt, ABCTimestamp):
803761
return dt.tz_localize(tz)
804762
return _localize_pydatetime(dt, tz)
805-
806-
807-
# ----------------------------------------------------------------------
808-
# Normalization
809-
810-
@cython.cdivision(False)
811-
cdef inline int64_t normalize_i8_stamp(int64_t local_val) nogil:
812-
"""
813-
Round the localized nanosecond timestamp down to the previous midnight.
814-
815-
Parameters
816-
----------
817-
local_val : int64_t
818-
819-
Returns
820-
-------
821-
int64_t
822-
"""
823-
cdef:
824-
int64_t day_nanos = 24 * 3600 * 1_000_000_000
825-
return local_val - (local_val % day_nanos)

pandas/_libs/tslibs/timestamps.pxd

+2
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ cdef class _Timestamp(ABCTimestamp):
2828
int op) except -1
2929
cpdef void _set_freq(self, freq)
3030
cdef _warn_on_field_deprecation(_Timestamp self, freq, str field)
31+
32+
cdef int64_t normalize_i8_stamp(int64_t local_val) nogil

pandas/_libs/tslibs/timestamps.pyx

+20-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ from pandas._libs.tslibs.conversion cimport (
5151
_TSObject,
5252
convert_datetime_to_tsobject,
5353
convert_to_tsobject,
54-
normalize_i8_stamp,
5554
)
5655
from pandas._libs.tslibs.util cimport (
5756
is_array,
@@ -2116,3 +2115,23 @@ cdef int64_t _NS_LOWER_BOUND = NPY_NAT + 1
21162115
Timestamp.min = Timestamp(_NS_LOWER_BOUND)
21172116
Timestamp.max = Timestamp(_NS_UPPER_BOUND)
21182117
Timestamp.resolution = Timedelta(nanoseconds=1) # GH#21336, GH#21365
2118+
2119+
2120+
# ----------------------------------------------------------------------
2121+
# Scalar analogues to functions in vectorized.pyx
2122+
2123+
2124+
@cython.cdivision(False)
2125+
cdef inline int64_t normalize_i8_stamp(int64_t local_val) nogil:
2126+
"""
2127+
Round the localized nanosecond timestamp down to the previous midnight.
2128+
2129+
Parameters
2130+
----------
2131+
local_val : int64_t
2132+
2133+
Returns
2134+
-------
2135+
int64_t
2136+
"""
2137+
return local_val - (local_val % ccalendar.DAY_NANOS)

pandas/_libs/tslibs/tzconversion.pxd

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from cpython.datetime cimport tzinfo
2-
from numpy cimport int64_t
2+
from numpy cimport (
3+
int64_t,
4+
intp_t,
5+
)
36

47

58
cdef int64_t localize_tzinfo_api(
@@ -11,3 +14,10 @@ cdef int64_t tz_localize_to_utc_single(
1114
) except? -1
1215

1316
cdef Py_ssize_t bisect_right_i8(int64_t *data, int64_t val, Py_ssize_t n)
17+
18+
cdef bint infer_datetuil_fold(
19+
int64_t value,
20+
const int64_t[::1] trans,
21+
const int64_t[::1] deltas,
22+
intp_t pos,
23+
)

pandas/_libs/tslibs/tzconversion.pyx

+45
Original file line numberDiff line numberDiff line change
@@ -632,3 +632,48 @@ cdef int64_t _tz_localize_using_tzinfo_api(
632632
td = tz.utcoffset(dt)
633633
delta = int(td.total_seconds() * 1_000_000_000)
634634
return delta
635+
636+
637+
# NB: relies on dateutil internals, subject to change.
638+
cdef bint infer_datetuil_fold(
639+
int64_t value,
640+
const int64_t[::1] trans,
641+
const int64_t[::1] deltas,
642+
intp_t pos,
643+
):
644+
"""
645+
Infer _TSObject fold property from value by assuming 0 and then setting
646+
to 1 if necessary.
647+
648+
Parameters
649+
----------
650+
value : int64_t
651+
trans : ndarray[int64_t]
652+
ndarray of offset transition points in nanoseconds since epoch.
653+
deltas : int64_t[:]
654+
array of offsets corresponding to transition points in trans.
655+
pos : intp_t
656+
Position of the last transition point before taking fold into account.
657+
658+
Returns
659+
-------
660+
bint
661+
Due to daylight saving time, one wall clock time can occur twice
662+
when shifting from summer to winter time; fold describes whether the
663+
datetime-like corresponds to the first (0) or the second time (1)
664+
the wall clock hits the ambiguous time
665+
666+
References
667+
----------
668+
.. [1] "PEP 495 - Local Time Disambiguation"
669+
https://www.python.org/dev/peps/pep-0495/#the-fold-attribute
670+
"""
671+
cdef:
672+
bint fold = 0
673+
674+
if pos > 0:
675+
fold_delta = deltas[pos - 1] - deltas[pos]
676+
if value - fold_delta < trans[pos]:
677+
fold = 1
678+
679+
return fold

pandas/_libs/tslibs/vectorized.pyx

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ from numpy cimport (
1818

1919
cnp.import_array()
2020

21-
from .conversion cimport normalize_i8_stamp
22-
2321
from .dtypes import Resolution
2422

2523
from .ccalendar cimport DAY_NANOS
@@ -34,7 +32,10 @@ from .np_datetime cimport (
3432
)
3533
from .offsets cimport BaseOffset
3634
from .period cimport get_period_ordinal
37-
from .timestamps cimport create_timestamp_from_ts
35+
from .timestamps cimport (
36+
create_timestamp_from_ts,
37+
normalize_i8_stamp,
38+
)
3839
from .timezones cimport (
3940
get_dst_info,
4041
is_tzlocal,

0 commit comments

Comments
 (0)