From 665083fec45c6ed4f6ba226bcbeb8dbcbee6302b Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 2 Nov 2017 20:54:13 -0700 Subject: [PATCH 01/15] Move normalization funcs up to conversion --- pandas/_libs/tslib.pyx | 145 +---------------------------- pandas/_libs/tslibs/conversion.pyx | 140 +++++++++++++++++++++++----- 2 files changed, 121 insertions(+), 164 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index bf22a3a528259..474aad60aee7e 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -97,13 +97,15 @@ from tslibs.conversion cimport (tz_convert_single, _TSObject, convert_to_tsobject, convert_datetime_to_tsobject, get_datetime64_nanos) -from tslibs.conversion import ( - tz_localize_to_utc, tz_convert, - tz_convert_single) +from tslibs.conversion import (tz_localize_to_utc, tz_convert, + tz_convert_single, date_normalize, + pydt_to_i8) from tslibs.nattype import NaT, nat_strings from tslibs.nattype cimport _checknull_with_nat +from tslibs.normalization import dates_normalized + cdef inline object create_timestamp_from_ts( int64_t value, pandas_datetimestruct dts, @@ -1849,19 +1851,6 @@ cdef inline _to_i8(object val): return val -cpdef pydt_to_i8(object pydt): - """ - Convert to int64 representation compatible with numpy datetime64; converts - to UTC - """ - cdef: - _TSObject ts - - ts = convert_to_tsobject(pydt, None, None, 0, 0) - - return ts.value - - def i8_to_pydt(int64_t i8, object tzinfo=None): """ Inverse of pydt_to_i8 @@ -1892,130 +1881,6 @@ def get_time_micros(ndarray[int64_t] dtindex): return micros -cdef int64_t DAY_NS = 86400000000000LL - - -@cython.wraparound(False) -@cython.boundscheck(False) -def date_normalize(ndarray[int64_t] stamps, tz=None): - cdef: - Py_ssize_t i, n = len(stamps) - pandas_datetimestruct dts - ndarray[int64_t] result = np.empty(n, dtype=np.int64) - - if tz is not None: - tz = maybe_get_tz(tz) - result = _normalize_local(stamps, tz) - else: - with nogil: - for i in range(n): - if stamps[i] == NPY_NAT: - result[i] = NPY_NAT - continue - dt64_to_dtstruct(stamps[i], &dts) - result[i] = _normalized_stamp(&dts) - - return result - - -@cython.wraparound(False) -@cython.boundscheck(False) -cdef _normalize_local(ndarray[int64_t] stamps, object tz): - cdef: - Py_ssize_t n = len(stamps) - ndarray[int64_t] result = np.empty(n, dtype=np.int64) - ndarray[int64_t] trans, deltas, pos - pandas_datetimestruct dts - - if is_utc(tz): - with nogil: - for i in range(n): - if stamps[i] == NPY_NAT: - result[i] = NPY_NAT - continue - dt64_to_dtstruct(stamps[i], &dts) - result[i] = _normalized_stamp(&dts) - elif is_tzlocal(tz): - for i in range(n): - if stamps[i] == NPY_NAT: - result[i] = NPY_NAT - continue - dt64_to_dtstruct(stamps[i], &dts) - dt = datetime(dts.year, dts.month, dts.day, dts.hour, - dts.min, dts.sec, dts.us, tz) - delta = int(get_utcoffset(tz, dt).total_seconds()) * 1000000000 - dt64_to_dtstruct(stamps[i] + delta, &dts) - result[i] = _normalized_stamp(&dts) - else: - # Adjust datetime64 timestamp, recompute datetimestruct - trans, deltas, typ = get_dst_info(tz) - - _pos = trans.searchsorted(stamps, side='right') - 1 - if _pos.dtype != np.int64: - _pos = _pos.astype(np.int64) - pos = _pos - - # statictzinfo - if typ not in ['pytz', 'dateutil']: - for i in range(n): - if stamps[i] == NPY_NAT: - result[i] = NPY_NAT - continue - dt64_to_dtstruct(stamps[i] + deltas[0], &dts) - result[i] = _normalized_stamp(&dts) - else: - for i in range(n): - if stamps[i] == NPY_NAT: - result[i] = NPY_NAT - continue - dt64_to_dtstruct(stamps[i] + deltas[pos[i]], &dts) - result[i] = _normalized_stamp(&dts) - - return result - -cdef inline int64_t _normalized_stamp(pandas_datetimestruct *dts) nogil: - dts.hour = 0 - dts.min = 0 - dts.sec = 0 - dts.us = 0 - dts.ps = 0 - return dtstruct_to_dt64(dts) - - -def dates_normalized(ndarray[int64_t] stamps, tz=None): - cdef: - Py_ssize_t i, n = len(stamps) - ndarray[int64_t] trans, deltas - pandas_datetimestruct dts - - if tz is None or is_utc(tz): - for i in range(n): - dt64_to_dtstruct(stamps[i], &dts) - if (dts.hour + dts.min + dts.sec + dts.us) > 0: - return False - elif is_tzlocal(tz): - for i in range(n): - dt64_to_dtstruct(stamps[i], &dts) - dt = datetime(dts.year, dts.month, dts.day, dts.hour, dts.min, - dts.sec, dts.us, tz) - dt = dt + tz.utcoffset(dt) - if (dt.hour + dt.minute + dt.second + dt.microsecond) > 0: - return False - else: - trans, deltas, typ = get_dst_info(tz) - - for i in range(n): - # Adjust datetime64 timestamp, recompute datetimestruct - pos = trans.searchsorted(stamps[i]) - 1 - inf = tz._transition_info[pos] - - dt64_to_dtstruct(stamps[i] + deltas[pos], &dts) - if (dts.hour + dts.min + dts.sec + dts.us) > 0: - return False - - return True - - # ---------------------------------------------------------------------- # Some general helper functions diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 61efc865112a9..83b6688b56592 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -53,7 +53,6 @@ UTC = pytz.UTC # ---------------------------------------------------------------------- # Misc Helpers - # TODO: How to declare np.datetime64 as the input type? cdef inline int64_t get_datetime64_nanos(object val) except? -1: """ @@ -90,6 +89,19 @@ cdef class _TSObject: return self.value +cpdef pydt_to_i8(object pydt): + """ + Convert to int64 representation compatible with numpy datetime64; converts + to UTC + """ + cdef: + _TSObject ts + + ts = convert_to_tsobject(pydt, None, None, 0, 0) + + return ts.value + + cdef convert_to_tsobject(object ts, object tz, object unit, bint dayfirst, bint yearfirst): """ @@ -335,17 +347,15 @@ cdef inline void _localize_tso(_TSObject obj, object tz): datetime dt if is_utc(tz): - obj.tzinfo = tz + pass + elif obj.value == NPY_NAT: + pass elif is_tzlocal(tz): dt64_to_dtstruct(obj.value, &obj.dts) dt = datetime(obj.dts.year, obj.dts.month, obj.dts.day, obj.dts.hour, obj.dts.min, obj.dts.sec, obj.dts.us, tz) delta = int(get_utcoffset(tz, dt).total_seconds()) * 1000000000 - if obj.value != NPY_NAT: - dt64_to_dtstruct(obj.value + delta, &obj.dts) - else: - dt64_to_dtstruct(obj.value, &obj.dts) - obj.tzinfo = tz + dt64_to_dtstruct(obj.value + delta, &obj.dts) else: # Adjust datetime64 timestamp, recompute datetimestruct trans, deltas, typ = get_dst_info(tz) @@ -355,26 +365,16 @@ cdef inline void _localize_tso(_TSObject obj, object tz): # static/pytz/dateutil specific code if is_fixed_offset(tz): # statictzinfo - if len(deltas) > 0 and obj.value != NPY_NAT: - dt64_to_dtstruct(obj.value + deltas[0], &obj.dts) - else: - dt64_to_dtstruct(obj.value, &obj.dts) - obj.tzinfo = tz + dt64_to_dtstruct(obj.value + deltas[0], &obj.dts) elif treat_tz_as_pytz(tz): - inf = tz._transition_info[pos] - if obj.value != NPY_NAT: - dt64_to_dtstruct(obj.value + deltas[pos], &obj.dts) - else: - dt64_to_dtstruct(obj.value, &obj.dts) - obj.tzinfo = tz._tzinfos[inf] + tz = tz._tzinfos[tz._transition_info[pos]] + dt64_to_dtstruct(obj.value + deltas[pos], &obj.dts) elif treat_tz_as_dateutil(tz): - if obj.value != NPY_NAT: - dt64_to_dtstruct(obj.value + deltas[pos], &obj.dts) - else: - dt64_to_dtstruct(obj.value, &obj.dts) - obj.tzinfo = tz + dt64_to_dtstruct(obj.value + deltas[pos], &obj.dts) else: - obj.tzinfo = tz + pass + + obj.tzinfo = tz cdef inline datetime _localize_pydatetime(datetime dt, tzinfo tz): @@ -782,3 +782,95 @@ cdef inline str _render_tstamp(int64_t val): """ Helper function to render exception messages""" from pandas._libs.tslib import Timestamp return str(Timestamp(val)) + + +# ---------------------------------------------------------------------- +# Normalization + +@cython.wraparound(False) +@cython.boundscheck(False) +def date_normalize(ndarray[int64_t] stamps, tz=None): + cdef: + Py_ssize_t i, n = len(stamps) + pandas_datetimestruct dts + ndarray[int64_t] result = np.empty(n, dtype=np.int64) + + if tz is not None: + tz = maybe_get_tz(tz) + result = _normalize_local(stamps, tz) + else: + with nogil: + for i in range(n): + if stamps[i] == NPY_NAT: + result[i] = NPY_NAT + continue + dt64_to_dtstruct(stamps[i], &dts) + result[i] = _normalized_stamp(&dts) + + return result + + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef _normalize_local(ndarray[int64_t] stamps, object tz): + cdef: + Py_ssize_t n = len(stamps) + ndarray[int64_t] result = np.empty(n, dtype=np.int64) + ndarray[int64_t] trans, deltas, pos + pandas_datetimestruct dts + datetime dt + + if is_utc(tz): + with nogil: + for i in range(n): + if stamps[i] == NPY_NAT: + result[i] = NPY_NAT + continue + dt64_to_dtstruct(stamps[i], &dts) + result[i] = _normalized_stamp(&dts) + elif is_tzlocal(tz): + for i in range(n): + if stamps[i] == NPY_NAT: + result[i] = NPY_NAT + continue + dt64_to_dtstruct(stamps[i], &dts) + dt = datetime(dts.year, dts.month, dts.day, dts.hour, + dts.min, dts.sec, dts.us, tz) + delta = int(get_utcoffset(tz, dt).total_seconds()) * 1000000000 + dt64_to_dtstruct(stamps[i] + delta, &dts) + result[i] = _normalized_stamp(&dts) + else: + # Adjust datetime64 timestamp, recompute datetimestruct + trans, deltas, typ = get_dst_info(tz) + + _pos = trans.searchsorted(stamps, side='right') - 1 + if _pos.dtype != np.int64: + _pos = _pos.astype(np.int64) + pos = _pos + + # statictzinfo + if typ not in ['pytz', 'dateutil']: + for i in range(n): + if stamps[i] == NPY_NAT: + result[i] = NPY_NAT + continue + dt64_to_dtstruct(stamps[i] + deltas[0], &dts) + result[i] = _normalized_stamp(&dts) + else: + for i in range(n): + if stamps[i] == NPY_NAT: + result[i] = NPY_NAT + continue + dt64_to_dtstruct(stamps[i] + deltas[pos[i]], &dts) + result[i] = _normalized_stamp(&dts) + + return result + + +cdef inline int64_t _normalized_stamp(pandas_datetimestruct *dts) nogil: + dts.hour = 0 + dts.min = 0 + dts.sec = 0 + dts.us = 0 + dts.ps = 0 + return dtstruct_to_dt64(dts) From 5481d7b114c8a1c41b4944c18e3d70cd025f902b Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 2 Nov 2017 22:08:25 -0700 Subject: [PATCH 02/15] fixup import typo --- pandas/_libs/tslib.pyx | 7 +++--- pandas/_libs/tslibs/conversion.pyx | 35 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index 474aad60aee7e..66f4aec5bfc06 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -97,14 +97,13 @@ from tslibs.conversion cimport (tz_convert_single, _TSObject, convert_to_tsobject, convert_datetime_to_tsobject, get_datetime64_nanos) -from tslibs.conversion import (tz_localize_to_utc, tz_convert, - tz_convert_single, date_normalize, - pydt_to_i8) +from tslibs.conversion import (tz_localize_to_utc, + tz_convert_single, date_normalize) +from tslibs.conversion import dates_normalized, pydt_to_i8, tz_convert # noqa from tslibs.nattype import NaT, nat_strings from tslibs.nattype cimport _checknull_with_nat -from tslibs.normalization import dates_normalized cdef inline object create_timestamp_from_ts( diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 83b6688b56592..8dad573786bc8 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -874,3 +874,38 @@ cdef inline int64_t _normalized_stamp(pandas_datetimestruct *dts) nogil: dts.us = 0 dts.ps = 0 return dtstruct_to_dt64(dts) + + +def dates_normalized(ndarray[int64_t] stamps, tz=None): + cdef: + Py_ssize_t i, n = len(stamps) + ndarray[int64_t] trans, deltas + pandas_datetimestruct dts + datetime dt + + if tz is None or is_utc(tz): + for i in range(n): + dt64_to_dtstruct(stamps[i], &dts) + if (dts.hour + dts.min + dts.sec + dts.us) > 0: + return False + elif is_tzlocal(tz): + for i in range(n): + dt64_to_dtstruct(stamps[i], &dts) + dt = datetime(dts.year, dts.month, dts.day, dts.hour, dts.min, + dts.sec, dts.us, tz) + dt = dt + tz.utcoffset(dt) + if (dt.hour + dt.minute + dt.second + dt.microsecond) > 0: + return False + else: + trans, deltas, typ = get_dst_info(tz) + + for i in range(n): + # Adjust datetime64 timestamp, recompute datetimestruct + pos = trans.searchsorted(stamps[i]) - 1 + inf = tz._transition_info[pos] + + dt64_to_dtstruct(stamps[i] + deltas[pos], &dts) + if (dts.hour + dts.min + dts.sec + dts.us) > 0: + return False + + return True From 9db556824ebb8358b51335eb5a4e21b447bff3c1 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Fri, 3 Nov 2017 07:57:47 -0700 Subject: [PATCH 03/15] whitespace fixup --- pandas/_libs/tslib.pyx | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index 66f4aec5bfc06..d9446ab28b444 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -105,7 +105,6 @@ from tslibs.nattype import NaT, nat_strings from tslibs.nattype cimport _checknull_with_nat - cdef inline object create_timestamp_from_ts( int64_t value, pandas_datetimestruct dts, object tz, object freq): From 57e6204786e2ccdfda0067955697239eb32ef9d5 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 7 Nov 2017 08:38:25 -0800 Subject: [PATCH 04/15] edits per reviewer request --- pandas/_libs/tslib.pyx | 2 +- pandas/_libs/tslibs/conversion.pyx | 3 ++- pandas/core/indexes/datetimes.py | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index d9446ab28b444..140fde4fd4de6 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -99,7 +99,7 @@ from tslibs.conversion cimport (tz_convert_single, _TSObject, get_datetime64_nanos) from tslibs.conversion import (tz_localize_to_utc, tz_convert_single, date_normalize) -from tslibs.conversion import dates_normalized, pydt_to_i8, tz_convert # noqa +from tslibs.conversion import pydt_to_i8, tz_convert # noqa from tslibs.nattype import NaT, nat_strings from tslibs.nattype cimport _checknull_with_nat diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 8dad573786bc8..bb5f85db81ce6 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -365,6 +365,7 @@ cdef inline void _localize_tso(_TSObject obj, object tz): # static/pytz/dateutil specific code if is_fixed_offset(tz): # statictzinfo + assert len(deltas) == 1, len(deltas) dt64_to_dtstruct(obj.value + deltas[0], &obj.dts) elif treat_tz_as_pytz(tz): tz = tz._tzinfos[tz._transition_info[pos]] @@ -876,7 +877,7 @@ cdef inline int64_t _normalized_stamp(pandas_datetimestruct *dts) nogil: return dtstruct_to_dt64(dts) -def dates_normalized(ndarray[int64_t] stamps, tz=None): +def are_dates_normalized(ndarray[int64_t] stamps, tz=None): cdef: Py_ssize_t i, n = len(stamps) ndarray[int64_t] trans, deltas diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 78869de318dce..501797c1310a6 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -56,7 +56,7 @@ algos as libalgos, join as libjoin, Timestamp, period as libperiod) from pandas._libs.tslibs import timezones - +from pandas._libs.tslibs.conversion import are_dates_normalized # -------- some conversion wrapper functions @@ -1683,7 +1683,7 @@ def is_normalized(self): """ Returns True if all of the dates are at midnight ("no time") """ - return libts.dates_normalized(self.asi8, self.tz) + return are_dates_normalized(self.asi8, self.tz) @cache_readonly def _resolution(self): From 1c7a1b19b76f9821a94411059280ca95ae68cacf Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 7 Nov 2017 09:08:23 -0800 Subject: [PATCH 05/15] assert obj.tzinfo is None inbound --- pandas/_libs/tslibs/conversion.pyx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index bb5f85db81ce6..eb4a468e68e49 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -346,6 +346,8 @@ cdef inline void _localize_tso(_TSObject obj, object tz): Py_ssize_t delta, posn datetime dt + assert obj.tzinfo is None + if is_utc(tz): pass elif obj.value == NPY_NAT: From 8192f870634e096db1a876fdb7713ab1e5694b38 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 7 Nov 2017 10:05:01 -0800 Subject: [PATCH 06/15] update imports --- pandas/_libs/tslib.pyx | 1 - pandas/_libs/tslibs/conversion.pxd | 2 ++ pandas/_libs/tslibs/offsets.pyx | 4 +--- pandas/core/indexes/datetimes.py | 33 +++++++++++++------------- pandas/tests/scalar/test_timestamp.py | 21 ++++++++-------- pandas/tests/tseries/test_timezones.py | 22 ++++++++--------- pandas/tseries/frequencies.py | 4 +++- 7 files changed, 44 insertions(+), 43 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index 140fde4fd4de6..c51c1bad01aa8 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -99,7 +99,6 @@ from tslibs.conversion cimport (tz_convert_single, _TSObject, get_datetime64_nanos) from tslibs.conversion import (tz_localize_to_utc, tz_convert_single, date_normalize) -from tslibs.conversion import pydt_to_i8, tz_convert # noqa from tslibs.nattype import NaT, nat_strings from tslibs.nattype cimport _checknull_with_nat diff --git a/pandas/_libs/tslibs/conversion.pxd b/pandas/_libs/tslibs/conversion.pxd index 843a688a2630c..77888e0946dcb 100644 --- a/pandas/_libs/tslibs/conversion.pxd +++ b/pandas/_libs/tslibs/conversion.pxd @@ -15,6 +15,8 @@ cdef class _TSObject: object tzinfo +cpdef pydt_to_i8(object pydt) + cdef convert_to_tsobject(object ts, object tz, object unit, bint dayfirst, bint yearfirst) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 87be9fa910101..dafa8244c6e19 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -15,10 +15,8 @@ np.import_array() from util cimport is_string_object -from pandas._libs.tslib import pydt_to_i8 - +from conversion cimport tz_convert_single, pydt_to_i8 from frequencies cimport get_freq_code -from conversion cimport tz_convert_single # --------------------------------------------------------------------- # Constants diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 501797c1310a6..3329cccfcdfec 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -55,8 +55,7 @@ from pandas._libs import (lib, index as libindex, tslib as libts, algos as libalgos, join as libjoin, Timestamp, period as libperiod) -from pandas._libs.tslibs import timezones -from pandas._libs.tslibs.conversion import are_dates_normalized +from pandas._libs.tslibs import timezones, conversion # -------- some conversion wrapper functions @@ -384,8 +383,8 @@ def __new__(cls, data=None, getattr(data, 'tz', None) is None): # Convert tz-naive to UTC ints = subarr.view('i8') - subarr = libts.tz_localize_to_utc(ints, tz, - ambiguous=ambiguous) + subarr = conversion.tz_localize_to_utc(ints, tz, + ambiguous=ambiguous) subarr = subarr.view(_NS_DTYPE) subarr = cls._simple_new(subarr, name=name, freq=freq, tz=tz) @@ -531,8 +530,8 @@ def _generate(cls, start, end, periods, name, offset, index = _generate_regular_range(start, end, periods, offset) if tz is not None and getattr(index, 'tz', None) is None: - index = libts.tz_localize_to_utc(_ensure_int64(index), tz, - ambiguous=ambiguous) + index = conversion.tz_localize_to_utc(_ensure_int64(index), tz, + ambiguous=ambiguous) index = index.view(_NS_DTYPE) # index is localized datetime64 array -> have to convert @@ -561,11 +560,11 @@ def _convert_for_op(self, value): def _local_timestamps(self): if self.is_monotonic: - return libts.tz_convert(self.asi8, utc, self.tz) + return conversion.tz_convert(self.asi8, utc, self.tz) else: values = self.asi8 indexer = values.argsort() - result = libts.tz_convert(values.take(indexer), utc, self.tz) + result = conversion.tz_convert(values.take(indexer), utc, self.tz) n = len(indexer) reverse = np.empty(n, dtype=np.int_) @@ -1644,7 +1643,7 @@ def normalize(self): ------- normalized : DatetimeIndex """ - new_values = libts.date_normalize(self.asi8, self.tz) + new_values = conversion.date_normalize(self.asi8, self.tz) return DatetimeIndex(new_values, freq='infer', name=self.name, tz=self.tz) @@ -1683,7 +1682,7 @@ def is_normalized(self): """ Returns True if all of the dates are at midnight ("no time") """ - return are_dates_normalized(self.asi8, self.tz) + return conversion.are_dates_normalized(self.asi8, self.tz) @cache_readonly def _resolution(self): @@ -1724,7 +1723,7 @@ def insert(self, loc, item): new_dates = np.concatenate((self[:loc].asi8, [item.view(np.int64)], self[loc:].asi8)) if self.tz is not None: - new_dates = libts.tz_convert(new_dates, 'UTC', self.tz) + new_dates = conversion.tz_convert(new_dates, 'UTC', self.tz) return DatetimeIndex(new_dates, name=self.name, freq=freq, tz=self.tz) @@ -1764,7 +1763,7 @@ def delete(self, loc): freq = self.freq if self.tz is not None: - new_dates = libts.tz_convert(new_dates, 'UTC', self.tz) + new_dates = conversion.tz_convert(new_dates, 'UTC', self.tz) return DatetimeIndex(new_dates, name=self.name, freq=freq, tz=self.tz) def tz_convert(self, tz): @@ -1844,16 +1843,16 @@ def tz_localize(self, tz, ambiguous='raise', errors='raise'): """ if self.tz is not None: if tz is None: - new_dates = libts.tz_convert(self.asi8, 'UTC', self.tz) + new_dates = conversion.tz_convert(self.asi8, 'UTC', self.tz) else: raise TypeError("Already tz-aware, use tz_convert to convert.") else: tz = timezones.maybe_get_tz(tz) # Convert to UTC - new_dates = libts.tz_localize_to_utc(self.asi8, tz, - ambiguous=ambiguous, - errors=errors) + new_dates = conversion.tz_localize_to_utc(self.asi8, tz, + ambiguous=ambiguous, + errors=errors) new_dates = new_dates.view(_NS_DTYPE) return self._shallow_copy(new_dates, tz=tz) @@ -2194,7 +2193,7 @@ def _to_m8(key, tz=None): # this also converts strings key = Timestamp(key, tz=tz) - return np.int64(libts.pydt_to_i8(key)).view(_NS_DTYPE) + return np.int64(conversion.pydt_to_i8(key)).view(_NS_DTYPE) _CACHE_START = Timestamp(datetime(1950, 1, 1)) diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index 4cd9a2fadeb32..517fc062fad80 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -18,6 +18,7 @@ from pandas.tseries import offsets, frequencies from pandas._libs import tslib, period from pandas._libs.tslibs.timezones import get_timezone +from pandas._libs.tslibs import conversion from pandas.compat import lrange, long, PY3 from pandas.util.testing import assert_series_equal @@ -77,12 +78,12 @@ def test_constructor(self): for result in [Timestamp(date_str), Timestamp(date)]: # only with timestring assert result.value == expected - assert tslib.pydt_to_i8(result) == expected + assert conversion.pydt_to_i8(result) == expected # re-creation shouldn't affect to internal value result = Timestamp(result) assert result.value == expected - assert tslib.pydt_to_i8(result) == expected + assert conversion.pydt_to_i8(result) == expected # with timezone for tz, offset in timezones: @@ -90,18 +91,18 @@ def test_constructor(self): tz=tz)]: expected_tz = expected - offset * 3600 * 1000000000 assert result.value == expected_tz - assert tslib.pydt_to_i8(result) == expected_tz + assert conversion.pydt_to_i8(result) == expected_tz # should preserve tz result = Timestamp(result) assert result.value == expected_tz - assert tslib.pydt_to_i8(result) == expected_tz + assert conversion.pydt_to_i8(result) == expected_tz # should convert to UTC result = Timestamp(result, tz='UTC') expected_utc = expected - offset * 3600 * 1000000000 assert result.value == expected_utc - assert tslib.pydt_to_i8(result) == expected_utc + assert conversion.pydt_to_i8(result) == expected_utc def test_constructor_with_stringoffset(self): # GH 7833 @@ -129,30 +130,30 @@ def test_constructor_with_stringoffset(self): for result in [Timestamp(date_str)]: # only with timestring assert result.value == expected - assert tslib.pydt_to_i8(result) == expected + assert conversion.pydt_to_i8(result) == expected # re-creation shouldn't affect to internal value result = Timestamp(result) assert result.value == expected - assert tslib.pydt_to_i8(result) == expected + assert conversion.pydt_to_i8(result) == expected # with timezone for tz, offset in timezones: result = Timestamp(date_str, tz=tz) expected_tz = expected assert result.value == expected_tz - assert tslib.pydt_to_i8(result) == expected_tz + assert conversion.pydt_to_i8(result) == expected_tz # should preserve tz result = Timestamp(result) assert result.value == expected_tz - assert tslib.pydt_to_i8(result) == expected_tz + assert conversion.pydt_to_i8(result) == expected_tz # should convert to UTC result = Timestamp(result, tz='UTC') expected_utc = expected assert result.value == expected_utc - assert tslib.pydt_to_i8(result) == expected_utc + assert conversion.pydt_to_i8(result) == expected_utc # This should be 2013-11-01 05:00 in UTC # converted to Chicago tz diff --git a/pandas/tests/tseries/test_timezones.py b/pandas/tests/tseries/test_timezones.py index ddcf1bb7d8b7b..fe340a7e3196f 100644 --- a/pandas/tests/tseries/test_timezones.py +++ b/pandas/tests/tseries/test_timezones.py @@ -17,7 +17,7 @@ from pandas.core.indexes.datetimes import bdate_range, date_range from pandas.core.dtypes.dtypes import DatetimeTZDtype from pandas._libs import tslib -from pandas._libs.tslibs import timezones +from pandas._libs.tslibs import timezones, conversion from pandas import (Index, Series, DataFrame, isna, Timestamp, NaT, DatetimeIndex, to_datetime) from pandas.util.testing import (assert_frame_equal, assert_series_equal, @@ -1732,14 +1732,14 @@ class TestTslib(object): def test_tslib_tz_convert(self): def compare_utc_to_local(tz_didx, utc_didx): - f = lambda x: tslib.tz_convert_single(x, 'UTC', tz_didx.tz) - result = tslib.tz_convert(tz_didx.asi8, 'UTC', tz_didx.tz) + f = lambda x: conversion_single(x, 'UTC', tz_didx.tz) + result = conversion(tz_didx.asi8, 'UTC', tz_didx.tz) result_single = np.vectorize(f)(tz_didx.asi8) tm.assert_numpy_array_equal(result, result_single) def compare_local_to_utc(tz_didx, utc_didx): - f = lambda x: tslib.tz_convert_single(x, tz_didx.tz, 'UTC') - result = tslib.tz_convert(utc_didx.asi8, tz_didx.tz, 'UTC') + f = lambda x: conversion_single(x, tz_didx.tz, 'UTC') + result = conversion(utc_didx.asi8, tz_didx.tz, 'UTC') result_single = np.vectorize(f)(utc_didx.asi8) tm.assert_numpy_array_equal(result, result_single) @@ -1764,14 +1764,14 @@ def compare_local_to_utc(tz_didx, utc_didx): compare_local_to_utc(tz_didx, utc_didx) # Check empty array - result = tslib.tz_convert(np.array([], dtype=np.int64), - timezones.maybe_get_tz('US/Eastern'), - timezones.maybe_get_tz('Asia/Tokyo')) + result = conversion.tz_convert(np.array([], dtype=np.int64), + timezones.maybe_get_tz('US/Eastern'), + timezones.maybe_get_tz('Asia/Tokyo')) tm.assert_numpy_array_equal(result, np.array([], dtype=np.int64)) # Check all-NaT array - result = tslib.tz_convert(np.array([tslib.iNaT], dtype=np.int64), - timezones.maybe_get_tz('US/Eastern'), - timezones.maybe_get_tz('Asia/Tokyo')) + result = conversion.tz_convert(np.array([tslib.iNaT], dtype=np.int64), + timezones.maybe_get_tz('US/Eastern'), + timezones.maybe_get_tz('Asia/Tokyo')) tm.assert_numpy_array_equal(result, np.array( [tslib.iNaT], dtype=np.int64)) diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index be25a439f9075..128dd51a2abea 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -21,6 +21,7 @@ from pandas._libs import lib, tslib from pandas._libs.tslib import Timedelta +from pandas._libs.tslibs import conversion from pandas._libs.tslibs.frequencies import ( # noqa get_freq_code, _base_and_stride, _period_str_to_code, _INVALID_FREQ_ERROR, opattern, _lite_rule_alias, _dont_uppercase, @@ -583,7 +584,8 @@ def __init__(self, index, warn=True): # the timezone so they are in local time if hasattr(index, 'tz'): if index.tz is not None: - self.values = tslib.tz_convert(self.values, 'UTC', index.tz) + self.values = conversion.tz_convert(self.values, + 'UTC', index.tz) self.warn = warn From 7b7e719d630db53097013ce13709deb7c629d175 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 7 Nov 2017 18:37:34 -0800 Subject: [PATCH 07/15] declare pydt_to_i8 in pxd --- pandas/_libs/tslibs/conversion.pxd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/_libs/tslibs/conversion.pxd b/pandas/_libs/tslibs/conversion.pxd index 77888e0946dcb..087020323b24c 100644 --- a/pandas/_libs/tslibs/conversion.pxd +++ b/pandas/_libs/tslibs/conversion.pxd @@ -28,3 +28,5 @@ cdef void _localize_tso(_TSObject obj, object tz) cpdef int64_t tz_convert_single(int64_t val, object tz1, object tz2) cdef int64_t get_datetime64_nanos(object val) except? -1 + +cpdef pydt_to_i8(object pydt) From 3c7e5aa254c3f50492c4396c1e3b264483aa5373 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 7 Nov 2017 21:38:24 -0800 Subject: [PATCH 08/15] typo fixup --- pandas/tests/scalar/test_timestamp.py | 2 +- pandas/tests/tseries/test_timezones.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index 517fc062fad80..a695de6952ae1 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -16,7 +16,7 @@ import pandas.util.testing as tm from pandas.tseries import offsets, frequencies -from pandas._libs import tslib, period +from pandas._libs import period from pandas._libs.tslibs.timezones import get_timezone from pandas._libs.tslibs import conversion diff --git a/pandas/tests/tseries/test_timezones.py b/pandas/tests/tseries/test_timezones.py index fe340a7e3196f..1604a1cd61f6b 100644 --- a/pandas/tests/tseries/test_timezones.py +++ b/pandas/tests/tseries/test_timezones.py @@ -1732,14 +1732,14 @@ class TestTslib(object): def test_tslib_tz_convert(self): def compare_utc_to_local(tz_didx, utc_didx): - f = lambda x: conversion_single(x, 'UTC', tz_didx.tz) - result = conversion(tz_didx.asi8, 'UTC', tz_didx.tz) + f = lambda x: conversion.tz_convert_single(x, 'UTC', tz_didx.tz) + result = conversion.tz_convert(tz_didx.asi8, 'UTC', tz_didx.tz) result_single = np.vectorize(f)(tz_didx.asi8) tm.assert_numpy_array_equal(result, result_single) def compare_local_to_utc(tz_didx, utc_didx): - f = lambda x: conversion_single(x, tz_didx.tz, 'UTC') - result = conversion(utc_didx.asi8, tz_didx.tz, 'UTC') + f = lambda x: conversion.tz_convert_single(x, tz_didx.tz, 'UTC') + result = conversion.tz_convert(utc_didx.asi8, tz_didx.tz, 'UTC') result_single = np.vectorize(f)(utc_didx.asi8) tm.assert_numpy_array_equal(result, result_single) From ec6757f04353d0c1d8083dbeac0ef9bf6a93dd71 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 7 Nov 2017 22:06:11 -0800 Subject: [PATCH 09/15] edits per reviewer request --- pandas/_libs/tslib.pyx | 7 ----- pandas/_libs/tslibs/conversion.pxd | 2 +- pandas/_libs/tslibs/conversion.pyx | 41 +++++++++++++++++++++++++++--- pandas/core/indexes/datetimes.py | 2 +- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index c51c1bad01aa8..b5285d158b1ed 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -1848,13 +1848,6 @@ cdef inline _to_i8(object val): return val -def i8_to_pydt(int64_t i8, object tzinfo=None): - """ - Inverse of pydt_to_i8 - """ - return Timestamp(i8) - - # ---------------------------------------------------------------------- # Accessors diff --git a/pandas/_libs/tslibs/conversion.pxd b/pandas/_libs/tslibs/conversion.pxd index 087020323b24c..98582c0c6d9c7 100644 --- a/pandas/_libs/tslibs/conversion.pxd +++ b/pandas/_libs/tslibs/conversion.pxd @@ -29,4 +29,4 @@ cpdef int64_t tz_convert_single(int64_t val, object tz1, object tz2) cdef int64_t get_datetime64_nanos(object val) except? -1 -cpdef pydt_to_i8(object pydt) +cpdef int64_t pydt_to_i8(object pydt) except? -1 \ No newline at end of file diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index eb4a468e68e49..178147e2ec375 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -89,7 +89,7 @@ cdef class _TSObject: return self.value -cpdef pydt_to_i8(object pydt): +cpdef int64_t pydt_to_i8(object pydt) except? -1: """ Convert to int64 representation compatible with numpy datetime64; converts to UTC @@ -102,6 +102,14 @@ cpdef pydt_to_i8(object pydt): return ts.value +def i8_to_pydt(int64_t i8, object tzinfo=None): + """ + Inverse of pydt_to_i8 + """ + from pandas import Timestamp + return Timestamp(i8) + + cdef convert_to_tsobject(object ts, object tz, object unit, bint dayfirst, bint yearfirst): """ @@ -793,6 +801,15 @@ cdef inline str _render_tstamp(int64_t val): @cython.wraparound(False) @cython.boundscheck(False) def date_normalize(ndarray[int64_t] stamps, tz=None): + """ + Normalize each of the (nanosecond) timestamps in the given array by + rounding down to the beginning of the day (i.e. midnight). If `tz` + is not None, then this is midnight for this timezone. + + Returns + ------- + result : int64 ndarray of converted of normalized nanosecond timestamps + """ cdef: Py_ssize_t i, n = len(stamps) pandas_datetimestruct dts @@ -815,7 +832,16 @@ def date_normalize(ndarray[int64_t] stamps, tz=None): @cython.wraparound(False) @cython.boundscheck(False) -cdef _normalize_local(ndarray[int64_t] stamps, object tz): +cdef ndarray[int64_t] _normalize_local(ndarray[int64_t] stamps, object tz): + """ + Normalize each of the (nanosecond) timestamps in the given array by + rounding down to the beginning of the day (i.e. midnight) for the + given timezone `tz`. + + Returns + ------- + result : int64 ndarray of converted of normalized nanosecond timestamps + """ cdef: Py_ssize_t n = len(stamps) ndarray[int64_t] result = np.empty(n, dtype=np.int64) @@ -879,7 +905,16 @@ cdef inline int64_t _normalized_stamp(pandas_datetimestruct *dts) nogil: return dtstruct_to_dt64(dts) -def are_dates_normalized(ndarray[int64_t] stamps, tz=None): +def bint is_date_array_normalized(ndarray[int64_t] stamps, tz=None): + """ + Check if all of the given (nanosecond) timestamps are normalized to + midnight, i.e. hour == minute == second == 0. If the optional timezone + `tz` is not None, then this is midnight for this timezone. + + Returns + ------- + is_normalizaed : bool True if all stamps are normalized + """ cdef: Py_ssize_t i, n = len(stamps) ndarray[int64_t] trans, deltas diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 3329cccfcdfec..8a1a36db5ac64 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -1682,7 +1682,7 @@ def is_normalized(self): """ Returns True if all of the dates are at midnight ("no time") """ - return conversion.are_dates_normalized(self.asi8, self.tz) + return conversion.is_date_array_normalized(self.asi8, self.tz) @cache_readonly def _resolution(self): From 07c95944151135a1b1a25d6c7b1095101dc8982b Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 8 Nov 2017 07:19:17 -0800 Subject: [PATCH 10/15] remove unallowed type declaration --- pandas/_libs/tslibs/conversion.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 178147e2ec375..9d1db0eb8b137 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -905,7 +905,7 @@ cdef inline int64_t _normalized_stamp(pandas_datetimestruct *dts) nogil: return dtstruct_to_dt64(dts) -def bint is_date_array_normalized(ndarray[int64_t] stamps, tz=None): +def is_date_array_normalized(ndarray[int64_t] stamps, tz=None): """ Check if all of the given (nanosecond) timestamps are normalized to midnight, i.e. hour == minute == second == 0. If the optional timezone From 505f740ed0d2323207c5a30a1a0eb25a48877deb Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 9 Nov 2017 07:56:27 -0800 Subject: [PATCH 11/15] edits per reviewer request --- pandas/_libs/tslibs/conversion.pyx | 36 +++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 9d1db0eb8b137..abe0b3d3cda7e 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -93,6 +93,14 @@ cpdef int64_t pydt_to_i8(object pydt) except? -1: """ Convert to int64 representation compatible with numpy datetime64; converts to UTC + + Parameters + ---------- + pydt : object + + Returns + ------- + i8value : np.int64 """ cdef: _TSObject ts @@ -806,6 +814,11 @@ def date_normalize(ndarray[int64_t] stamps, tz=None): rounding down to the beginning of the day (i.e. midnight). If `tz` is not None, then this is midnight for this timezone. + Parameters + ---------- + stamps : int64 ndarray + tz : tzinfo or None + Returns ------- result : int64 ndarray of converted of normalized nanosecond timestamps @@ -838,6 +851,11 @@ cdef ndarray[int64_t] _normalize_local(ndarray[int64_t] stamps, object tz): rounding down to the beginning of the day (i.e. midnight) for the given timezone `tz`. + Parameters + ---------- + stamps : int64 ndarray + tz : tzinfo or None + Returns ------- result : int64 ndarray of converted of normalized nanosecond timestamps @@ -897,6 +915,17 @@ cdef ndarray[int64_t] _normalize_local(ndarray[int64_t] stamps, object tz): cdef inline int64_t _normalized_stamp(pandas_datetimestruct *dts) nogil: + """ + Normalize the given datetimestruct to midnight, then convert to int64_t. + + Parameters + ---------- + *dts : pointer to pandas_datetimestruct + + Returns + ------- + stamp : int64 + """ dts.hour = 0 dts.min = 0 dts.sec = 0 @@ -911,9 +940,14 @@ def is_date_array_normalized(ndarray[int64_t] stamps, tz=None): midnight, i.e. hour == minute == second == 0. If the optional timezone `tz` is not None, then this is midnight for this timezone. + Parameters + ---------- + stamps : int64 ndarray + tz : tzinfo or None + Returns ------- - is_normalizaed : bool True if all stamps are normalized + is_normalized : bool True if all stamps are normalized """ cdef: Py_ssize_t i, n = len(stamps) From e7456ce124ab376dba26729bd18d326ab4d8c49b Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 9 Nov 2017 09:26:44 -0800 Subject: [PATCH 12/15] dummy commit to force CI --- pandas/_libs/groupby.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/_libs/groupby.pyx b/pandas/_libs/groupby.pyx index 2fbbc81c4b5a1..e1312a40971f0 100644 --- a/pandas/_libs/groupby.pyx +++ b/pandas/_libs/groupby.pyx @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # cython: profile=False cimport numpy as cnp From 69d086556c9ea3bcfcb5656fba176da444b112b8 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 12 Nov 2017 10:48:13 -0800 Subject: [PATCH 13/15] remove duplicate declaration --- pandas/_libs/tslibs/conversion.pxd | 2 -- 1 file changed, 2 deletions(-) diff --git a/pandas/_libs/tslibs/conversion.pxd b/pandas/_libs/tslibs/conversion.pxd index 98582c0c6d9c7..2423a273bdbd1 100644 --- a/pandas/_libs/tslibs/conversion.pxd +++ b/pandas/_libs/tslibs/conversion.pxd @@ -15,8 +15,6 @@ cdef class _TSObject: object tzinfo -cpdef pydt_to_i8(object pydt) - cdef convert_to_tsobject(object ts, object tz, object unit, bint dayfirst, bint yearfirst) From 84594cb2af61503070a1f4ee76cb698c71b4806b Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 12 Nov 2017 10:48:35 -0800 Subject: [PATCH 14/15] whitespace fixup --- pandas/_libs/tslibs/conversion.pxd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/conversion.pxd b/pandas/_libs/tslibs/conversion.pxd index 2423a273bdbd1..ad817ce8852f2 100644 --- a/pandas/_libs/tslibs/conversion.pxd +++ b/pandas/_libs/tslibs/conversion.pxd @@ -27,4 +27,4 @@ cpdef int64_t tz_convert_single(int64_t val, object tz1, object tz2) cdef int64_t get_datetime64_nanos(object val) except? -1 -cpdef int64_t pydt_to_i8(object pydt) except? -1 \ No newline at end of file +cpdef int64_t pydt_to_i8(object pydt) except? -1 From 3fa05bd68c8cb2a794b1d39f392ca4f4c8ef26c1 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 12 Nov 2017 11:04:04 -0800 Subject: [PATCH 15/15] remove i8_to_pydt per request --- pandas/_libs/tslibs/conversion.pyx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index abe0b3d3cda7e..88372699911c4 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -110,14 +110,6 @@ cpdef int64_t pydt_to_i8(object pydt) except? -1: return ts.value -def i8_to_pydt(int64_t i8, object tzinfo=None): - """ - Inverse of pydt_to_i8 - """ - from pandas import Timestamp - return Timestamp(i8) - - cdef convert_to_tsobject(object ts, object tz, object unit, bint dayfirst, bint yearfirst): """