Skip to content

Move time conversion funcs to tslibs.conversion #17708

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 1 addition & 27 deletions pandas/_libs/index.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,19 @@ cimport util

import numpy as np

cimport tslib

from hashtable cimport HashTable

from tslibs.timezones cimport is_utc, get_utcoffset
from tslibs.conversion cimport _to_i8
from pandas._libs import tslib, algos, hashtable as _hash
from pandas._libs.tslib import Timestamp, Timedelta
from datetime import datetime, timedelta

from datetime cimport (get_datetime64_value, _pydatetime_to_dts,
pandas_datetimestruct)

from cpython cimport PyTuple_Check, PyList_Check

cdef extern from "datetime.h":
bint PyDateTime_Check(object o)
void PyDateTime_IMPORT()

cdef int64_t iNaT = util.get_nat()


PyDateTime_IMPORT

cdef extern from "Python.h":
int PySlice_Check(object)
Expand Down Expand Up @@ -540,23 +531,6 @@ cpdef convert_scalar(ndarray arr, object value):

return value

cdef inline _to_i8(object val):
cdef pandas_datetimestruct dts
try:
return val.value
except AttributeError:
if util.is_datetime64_object(val):
return get_datetime64_value(val)
elif PyDateTime_Check(val):
tzinfo = getattr(val, 'tzinfo', None)
# Save the original date value so we can get the utcoffset from it.
ival = _pydatetime_to_dts(val, &dts)
if tzinfo is not None and not is_utc(tzinfo):
offset = get_utcoffset(tzinfo, val)
ival -= tslib._delta_to_nanoseconds(offset)
return ival
return val


cdef class MultiIndexObjectEngine(ObjectEngine):
"""
Expand Down
58 changes: 4 additions & 54 deletions pandas/_libs/lib.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ cdef double NaN = <double> np.NaN
cdef double nan = NaN
cdef double NAN = nan

from datetime import datetime as pydatetime

# this is our tseries.pxd
from datetime cimport (
get_timedelta64_value, get_datetime64_value,
Expand Down Expand Up @@ -134,58 +132,10 @@ def memory_usage_of_objects(ndarray[object, ndim=1] arr):

#----------------------------------------------------------------------
# datetime / io related

cdef int _EPOCH_ORD = 719163

from datetime import date as pydate

cdef inline int64_t gmtime(object date):
cdef int y, m, d, h, mn, s, days

y = PyDateTime_GET_YEAR(date)
m = PyDateTime_GET_MONTH(date)
d = PyDateTime_GET_DAY(date)
h = PyDateTime_DATE_GET_HOUR(date)
mn = PyDateTime_DATE_GET_MINUTE(date)
s = PyDateTime_DATE_GET_SECOND(date)

days = pydate(y, m, 1).toordinal() - _EPOCH_ORD + d - 1
return ((<int64_t> (((days * 24 + h) * 60 + mn))) * 60 + s) * 1000


cpdef object to_datetime(int64_t timestamp):
return pydatetime.utcfromtimestamp(timestamp / 1000.0)


cpdef object to_timestamp(object dt):
return gmtime(dt)


def array_to_timestamp(ndarray[object, ndim=1] arr):
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this is called anywhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

Doesn't look like it, no. But its def and not cdef, so conceivably used downstream. OK to remove?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes ok to remove

Copy link
Contributor

Choose a reason for hiding this comment

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

these are ALL private modules (did that on purpose), so can move code around as long as we are internally consistent

cdef int i, n
cdef ndarray[int64_t, ndim=1] result

n = len(arr)
result = np.empty(n, dtype=np.int64)

for i from 0 <= i < n:
result[i] = gmtime(arr[i])

return result


def time64_to_datetime(ndarray[int64_t, ndim=1] arr):
Copy link
Contributor

Choose a reason for hiding this comment

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

this is just a simple call to pd.to_datetime

Copy link
Member Author

Choose a reason for hiding this comment

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

This is only used in io.pytables. OK to replace then remove?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, I think you can just replace that call in pytables

cdef int i, n
cdef ndarray[object, ndim=1] result

n = len(arr)
result = np.empty(n, dtype=object)

for i from 0 <= i < n:
result[i] = to_datetime(arr[i])

return result

from tslibs.conversion import ( # noqa
time64_to_datetime,
array_to_timestamp, to_timestamp, to_datetime)
from tslibs.conversion cimport to_timestamp, to_datetime, gmtime # noqa

#----------------------------------------------------------------------
# isnull / notnull related
Expand Down
10 changes: 10 additions & 0 deletions pandas/_libs/tslibs/conversion.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# cython: profile=False

from numpy cimport int64_t

cdef int64_t gmtime(object date)
cpdef object to_datetime(int64_t timestamp)
cpdef object to_timestamp(object dt)

cdef _to_i8(object val)
104 changes: 104 additions & 0 deletions pandas/_libs/tslibs/conversion.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
# cython: profile=False


from datetime import (
date as pydate,
datetime as pydatetime)

from cpython.datetime cimport (
PyDateTime_Check,
PyDateTime_GET_YEAR,
PyDateTime_GET_MONTH,
PyDateTime_GET_DAY,
PyDateTime_DATE_GET_HOUR,
PyDateTime_DATE_GET_MINUTE,
PyDateTime_DATE_GET_SECOND,
PyDateTime_IMPORT)
PyDateTime_IMPORT

from datetime cimport (get_datetime64_value, _pydatetime_to_dts,
pandas_datetimestruct)

import numpy as np
cimport numpy as cnp
from numpy cimport int64_t, ndarray
cnp.import_array()

cimport util

from timezones cimport get_utcoffset, is_utc

# ----------------------------------------------------------------------
# Constants
cdef int _EPOCH_ORD = 719163

# ----------------------------------------------------------------------
# Non-pandas-specific

cpdef object to_datetime(int64_t timestamp):
return pydatetime.utcfromtimestamp(timestamp / 1000.0)


cdef inline int64_t gmtime(object date):
cdef int y, m, d, h, mn, s, days

y = PyDateTime_GET_YEAR(date)
m = PyDateTime_GET_MONTH(date)
d = PyDateTime_GET_DAY(date)
h = PyDateTime_DATE_GET_HOUR(date)
mn = PyDateTime_DATE_GET_MINUTE(date)
s = PyDateTime_DATE_GET_SECOND(date)

days = pydate(y, m, 1).toordinal() - _EPOCH_ORD + d - 1
return ((<int64_t> (((days * 24 + h) * 60 + mn))) * 60 + s) * 1000


cpdef object to_timestamp(object dt):
return gmtime(dt)


def array_to_timestamp(ndarray[object, ndim=1] arr):
cdef int i, n
cdef ndarray[int64_t, ndim=1] result

n = len(arr)
result = np.empty(n, dtype=np.int64)

for i in range(n):
result[i] = gmtime(arr[i])

return result


def time64_to_datetime(ndarray[int64_t, ndim=1] arr):
cdef int i, n
cdef ndarray[object, ndim=1] result

n = len(arr)
result = np.empty(n, dtype=object)

for i in range(n):
result[i] = to_datetime(arr[i])

return result


# ----------------------------------------------------------------------

cdef inline _to_i8(object val):
cdef pandas_datetimestruct dts
try:
return val.value
except AttributeError:
if util.is_datetime64_object(val):
return get_datetime64_value(val)
elif PyDateTime_Check(val):
tzinfo = getattr(val, 'tzinfo', None)
# Save the original date value so we can get the utcoffset from it.
ival = _pydatetime_to_dts(val, &dts)
if tzinfo is not None and not is_utc(tzinfo):
offset = get_utcoffset(tzinfo, val)
ival -= int(offset.total_seconds() * 1e9)
return ival
return val
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ class CheckSDist(sdist_class):
'pandas/_libs/window.pyx',
'pandas/_libs/sparse.pyx',
'pandas/_libs/parsers.pyx',
'pandas/_libs/tslibs/conversion.pyx',
'pandas/_libs/tslibs/timezones.pyx',
'pandas/_libs/tslibs/frequencies.pyx',
'pandas/_libs/tslibs/parsing.pyx',
Expand Down Expand Up @@ -492,6 +493,7 @@ def pxd(name):
'depends': tseries_depends,
'sources': ['pandas/_libs/src/datetime/np_datetime.c',
'pandas/_libs/src/datetime/np_datetime_strings.c']},
'_libs.tslibs.conversion': {'pyxfile': '_libs/tslibs/conversion'},
'_libs.tslibs.timezones': {'pyxfile': '_libs/tslibs/timezones'},
'_libs.period': {'pyxfile': '_libs/period',
'depends': (tseries_depends +
Expand Down