Skip to content

Implement tslibs.__init__, move easy bits of tslib #21738

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 4 commits into from
Jul 5, 2018
Merged
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
55 changes: 2 additions & 53 deletions pandas/_libs/tslib.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,17 @@ from cython cimport Py_ssize_t


import pytz
UTC = pytz.utc


from tslibs.timedeltas cimport cast_from_unit
from tslibs.timedeltas import Timedelta
from tslibs.timedeltas import Timedelta, ints_to_pytimedelta # noqa:F841
from tslibs.timezones cimport (is_utc, is_tzlocal, is_fixed_offset,
treat_tz_as_pytz, get_dst_info)
from tslibs.conversion cimport (tz_convert_single, _TSObject,
convert_datetime_to_tsobject,
get_datetime64_nanos,
tz_convert_utc_to_tzlocal)
from tslibs.conversion import tz_convert_single
from tslibs.conversion import tz_convert_single, normalize_date # noqa:F841

from tslibs.nattype import NaT, nat_strings, iNaT
from tslibs.nattype cimport checknull_with_nat, NPY_NAT
Expand Down Expand Up @@ -185,29 +184,6 @@ def ints_to_pydatetime(ndarray[int64_t] arr, tz=None, freq=None,
return result


def ints_to_pytimedelta(ndarray[int64_t] arr, box=False):
# convert an i8 repr to an ndarray of timedelta or Timedelta (if box ==
# True)

cdef:
Py_ssize_t i, n = len(arr)
int64_t value
ndarray[object] result = np.empty(n, dtype=object)

for i in range(n):

value = arr[i]
if value == NPY_NAT:
result[i] = NaT
else:
if box:
result[i] = Timedelta(value)
else:
result[i] = timedelta(microseconds=int(value) / 1000)

return result


def _test_parse_iso8601(object ts):
"""
TESTING ONLY: Parse string into Timestamp using iso8601 parser. Used
Expand Down Expand Up @@ -740,30 +716,3 @@ cdef inline bint _parse_today_now(str val, int64_t* iresult):
iresult[0] = Timestamp.today().value
return True
return False

# ----------------------------------------------------------------------
# Some general helper functions


cpdef normalize_date(object dt):
"""
Normalize datetime.datetime value to midnight. Returns datetime.date as a
datetime.datetime at midnight

Returns
-------
normalized : datetime.datetime or Timestamp
"""
if PyDateTime_Check(dt):
if not PyDateTime_CheckExact(dt):
# i.e. a Timestamp object
return dt.replace(hour=0, minute=0, second=0, microsecond=0,
nanosecond=0)
else:
# regular datetime object
return dt.replace(hour=0, minute=0, second=0, microsecond=0)
# TODO: Make sure DST crossing is handled correctly here
elif PyDate_Check(dt):
return datetime(dt.year, dt.month, dt.day)
else:
raise TypeError('Unrecognized type: %s' % type(dt))
8 changes: 7 additions & 1 deletion pandas/_libs/tslibs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
# -*- coding: utf-8 -*-
# cython: profile=False
# flake8: noqa

from .conversion import normalize_date, localize_pydatetime, tz_convert_single
from .nattype import NaT, iNaT
Copy link
Contributor

Choose a reason for hiding this comment

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

next PR should have a test that exercises what is in this API, name it test_api.py and check that the namespace is locked down)

from .np_datetime import OutOfBoundsDatetime
from .timestamps import Timestamp
from .timedeltas import delta_to_nanoseconds, ints_to_pytimedelta, Timedelta
29 changes: 29 additions & 0 deletions pandas/_libs/tslibs/conversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,35 @@ cdef inline str _render_tstamp(int64_t val):
# ----------------------------------------------------------------------
# Normalization


def normalize_date(object dt):
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

we ought to fix these names (prob rename date_normalize) in future PR

Normalize datetime.datetime value to midnight. Returns datetime.date as a
datetime.datetime at midnight

Parameters
----------
dt : date, datetime, or Timestamp

Returns
-------
normalized : datetime.datetime or Timestamp
Copy link
Contributor

Choose a reason for hiding this comment

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

add a raises section

"""
if PyDateTime_Check(dt):
if not PyDateTime_CheckExact(dt):
# i.e. a Timestamp object
return dt.replace(hour=0, minute=0, second=0, microsecond=0,
nanosecond=0)
else:
# regular datetime object
return dt.replace(hour=0, minute=0, second=0, microsecond=0)
# TODO: Make sure DST crossing is handled correctly here
elif PyDate_Check(dt):
return datetime(dt.year, dt.month, dt.day)
else:
raise TypeError('Unrecognized type: %s' % type(dt))


@cython.wraparound(False)
@cython.boundscheck(False)
def date_normalize(ndarray[int64_t] stamps, tz=None):
Expand Down
38 changes: 38 additions & 0 deletions pandas/_libs/tslibs/timedeltas.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,44 @@ cdef dict timedelta_abbrevs = { 'D': 'd',

_no_input = object()


# ----------------------------------------------------------------------
# API

def ints_to_pytimedelta(ndarray[int64_t] arr, box=False):
"""
convert an i8 repr to an ndarray of timedelta or Timedelta (if box ==
True)

Parameters
----------
arr : ndarray[int64_t]
box : bool, default False

Returns
-------
result : ndarray[object]
array of Timedelta or timedeltas objects
"""
cdef:
Py_ssize_t i, n = len(arr)
int64_t value
ndarray[object] result = np.empty(n, dtype=object)

for i in range(n):

value = arr[i]
if value == NPY_NAT:
result[i] = NaT
else:
if box:
result[i] = Timedelta(value)
else:
result[i] = timedelta(microseconds=int(value) / 1000)

return result


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

cpdef int64_t delta_to_nanoseconds(delta) except? -1:
Expand Down
1 change: 0 additions & 1 deletion pandas/_libs/tslibs/timestamps.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,6 @@ class Timestamp(_Timestamp):
return NaT

if is_string_object(freq):
from pandas.tseries.frequencies import to_offset
freq = to_offset(freq)

return create_timestamp_from_ts(ts.value, ts.dts, ts.tzinfo, freq)
Expand Down
2 changes: 0 additions & 2 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7156,7 +7156,6 @@ def first(self, offset):
at_time : Select values at a particular time of the day
between_time : Select values between particular times of the day
"""
from pandas.tseries.frequencies import to_offset
if not isinstance(self.index, DatetimeIndex):
raise TypeError("'first' only supports a DatetimeIndex index")

Expand Down Expand Up @@ -7220,7 +7219,6 @@ def last(self, offset):
at_time : Select values at a particular time of the day
between_time : Select values between particular times of the day
"""
from pandas.tseries.frequencies import to_offset
if not isinstance(self.index, DatetimeIndex):
raise TypeError("'last' only supports a DatetimeIndex index")

Expand Down
7 changes: 1 addition & 6 deletions pandas/tests/tseries/offsets/test_offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import pandas.tseries.offsets as offsets
from pandas.io.pickle import read_pickle
from pandas._libs.tslibs import timezones
from pandas._libs.tslib import normalize_date, NaT, Timestamp
from pandas._libs.tslib import NaT, Timestamp
import pandas._libs.tslib as tslib
import pandas.util.testing as tm
from pandas.tseries.holiday import USFederalHolidayCalendar
Expand All @@ -59,11 +59,6 @@ def test_ole2datetime():
ole2datetime(60)


def test_normalize_date():
actual = normalize_date(datetime(2007, 10, 1, 1, 12, 5, 10))
assert actual == datetime(2007, 10, 1)


def test_to_m8():
valb = datetime(2007, 10, 1)
valu = _to_m8(valb)
Expand Down
5 changes: 5 additions & 0 deletions pandas/tests/tslibs/test_tslib.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ def test_normalize_date():

result = tslib.normalize_date(value)
assert (result == datetime(2012, 9, 7))

value = datetime(2007, 10, 1, 1, 12, 5, 10)

actual = tslib.normalize_date(value)
assert actual == datetime(2007, 10, 1)