diff --git a/pandas/_libs/missing.pxd b/pandas/_libs/missing.pxd index f3d990db1c3fd..b90975df8e247 100644 --- a/pandas/_libs/missing.pxd +++ b/pandas/_libs/missing.pxd @@ -1,6 +1,11 @@ # -*- coding: utf-8 -*- # cython: profile=False -cdef bint is_null_datetimelike(object val) +from tslibs.nattype cimport is_null_datetimelike + cpdef bint checknull(object val) cpdef bint checknull_old(object val) + +cdef bint is_null_datetime64(v) +cdef bint is_null_timedelta64(v) +cdef bint is_null_period(v) diff --git a/pandas/_libs/missing.pyx b/pandas/_libs/missing.pyx index dfd044131afb4..79c30ac5f3778 100644 --- a/pandas/_libs/missing.pyx +++ b/pandas/_libs/missing.pyx @@ -15,6 +15,7 @@ cimport util from tslibs.np_datetime cimport get_timedelta64_value, get_datetime64_value from tslibs.nattype import NaT +from tslibs.nattype cimport is_null_datetimelike cdef double INF = np.inf cdef double NEGINF = -INF @@ -22,22 +23,6 @@ cdef double NEGINF = -INF cdef int64_t NPY_NAT = util.get_nat() -cdef inline bint is_null_datetimelike(object val): - # determine if we have a null for a timedelta/datetime (or integer - # versions) - if util._checknull(val): - return True - elif val is NaT: - return True - elif util.is_timedelta64_object(val): - return val.view('int64') == NPY_NAT - elif util.is_datetime64_object(val): - return val.view('int64') == NPY_NAT - elif util.is_integer_object(val): - return val == NPY_NAT - return False - - cdef inline bint _check_all_nulls(object val): """ utility to check if a value is any type of null """ cdef bint res @@ -308,3 +293,37 @@ cpdef bint isneginf_scalar(object val): return True else: return False + + +cdef inline bint is_null_datetime64(v): + # determine if we have a null for a datetime (or integer versions), + # excluding np.timedelta64('nat') + if util._checknull(v): + return True + elif v is NaT: + return True + elif util.is_datetime64_object(v): + return v.view('int64') == NPY_NAT + return False + + +cdef inline bint is_null_timedelta64(v): + # determine if we have a null for a timedelta (or integer versions), + # excluding np.datetime64('nat') + if util._checknull(v): + return True + elif v is NaT: + return True + elif util.is_timedelta64_object(v): + return v.view('int64') == NPY_NAT + return False + + +cdef inline bint is_null_period(v): + # determine if we have a null for a Period (or integer versions), + # excluding np.datetime64('nat') and np.timedelta64('nat') + if util._checknull(v): + return True + elif v is NaT: + return True + return False diff --git a/pandas/_libs/src/inference.pyx b/pandas/_libs/src/inference.pyx index cf887ce1a6387..8cf69057a7e74 100644 --- a/pandas/_libs/src/inference.pyx +++ b/pandas/_libs/src/inference.pyx @@ -28,6 +28,8 @@ cdef extern from "numpy/arrayobject.h": cdef object fields cdef tuple names +from missing cimport is_null_datetime64, is_null_timedelta64, is_null_period + from util cimport UINT8_MAX, UINT64_MAX, INT64_MAX, INT64_MIN # core.common import for fast inference checks @@ -574,40 +576,6 @@ cpdef object infer_datetimelike_array(object arr): return 'mixed' -cdef inline bint is_null_datetime64(v): - # determine if we have a null for a datetime (or integer versions), - # excluding np.timedelta64('nat') - if util._checknull(v): - return True - elif v is NaT: - return True - elif util.is_datetime64_object(v): - return v.view('int64') == iNaT - return False - - -cdef inline bint is_null_timedelta64(v): - # determine if we have a null for a timedelta (or integer versions), - # excluding np.datetime64('nat') - if util._checknull(v): - return True - elif v is NaT: - return True - elif util.is_timedelta64_object(v): - return v.view('int64') == iNaT - return False - - -cdef inline bint is_null_period(v): - # determine if we have a null for a Period (or integer versions), - # excluding np.datetime64('nat') and np.timedelta64('nat') - if util._checknull(v): - return True - elif v is NaT: - return True - return False - - cdef inline bint is_datetime(object o): return PyDateTime_Check(o) diff --git a/pandas/_libs/tslibs/nattype.pxd b/pandas/_libs/tslibs/nattype.pxd index 96e02142d501b..24ce797575b2a 100644 --- a/pandas/_libs/tslibs/nattype.pxd +++ b/pandas/_libs/tslibs/nattype.pxd @@ -7,3 +7,4 @@ cdef int64_t NPY_NAT cdef bint _nat_scalar_rules[6] cdef bint checknull_with_nat(object val) +cdef bint is_null_datetimelike(object val) diff --git a/pandas/_libs/tslibs/nattype.pyx b/pandas/_libs/tslibs/nattype.pyx index be76b55fa169b..2fe8fab2e2e19 100644 --- a/pandas/_libs/tslibs/nattype.pyx +++ b/pandas/_libs/tslibs/nattype.pyx @@ -16,6 +16,7 @@ cimport numpy as cnp from numpy cimport int64_t cnp.import_array() +cimport util from util cimport (get_nat, is_integer_object, is_float_object, is_datetime64_object, is_timedelta64_object) @@ -587,3 +588,28 @@ cdef inline bint checknull_with_nat(object val): """ utility to check if a value is a nat or not """ return val is None or ( PyFloat_Check(val) and val != val) or val is NaT + + +cdef inline bint is_null_datetimelike(object val): + """ + Determine if we have a null for a timedelta/datetime (or integer versions) + + Parameters + ---------- + val : object + + Returns + ------- + null_datetimelike : bool + """ + if util._checknull(val): + return True + elif val is NaT: + return True + elif util.is_timedelta64_object(val): + return val.view('int64') == NPY_NAT + elif util.is_datetime64_object(val): + return val.view('int64') == NPY_NAT + elif util.is_integer_object(val): + return val == NPY_NAT + return False diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 6661eb2bccb3c..6e5794ef41757 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -36,8 +36,6 @@ cdef extern from "../src/datetime/np_datetime.h": cimport util from util cimport is_period_object, is_string_object, INT32_MIN -from pandas._libs.missing cimport is_null_datetimelike - from timestamps import Timestamp from timezones cimport is_utc, is_tzlocal, get_utcoffset, get_dst_info from timedeltas cimport delta_to_nanoseconds @@ -52,7 +50,7 @@ from frequencies cimport (get_freq_code, get_base_alias, from parsing import parse_time_string, NAT_SENTINEL from resolution import Resolution from nattype import nat_strings, NaT, iNaT -from nattype cimport _nat_scalar_rules, NPY_NAT +from nattype cimport _nat_scalar_rules, NPY_NAT, is_null_datetimelike from offsets cimport to_offset from pandas.tseries import offsets diff --git a/setup.py b/setup.py index 75e2b18409e19..29b19fed0e2d4 100755 --- a/setup.py +++ b/setup.py @@ -531,17 +531,6 @@ def pxd(name): 'pyxfile': '_libs/ops', 'pxdfiles': ['_libs/src/util', '_libs/missing']}, - '_libs.tslibs.period': { - 'pyxfile': '_libs/tslibs/period', - 'pxdfiles': ['_libs/src/util', - '_libs/missing', - '_libs/tslibs/ccalendar', - '_libs/tslibs/timedeltas', - '_libs/tslibs/timezones', - '_libs/tslibs/nattype', - '_libs/tslibs/offsets'], - 'depends': tseries_depends + ['pandas/_libs/src/period_helper.h'], - 'sources': np_datetime_sources + ['pandas/_libs/src/period_helper.c']}, '_libs.properties': { 'pyxfile': '_libs/properties', 'include': []}, @@ -603,6 +592,16 @@ def pxd(name): '_libs.tslibs.parsing': { 'pyxfile': '_libs/tslibs/parsing', 'pxdfiles': ['_libs/src/util']}, + '_libs.tslibs.period': { + 'pyxfile': '_libs/tslibs/period', + 'pxdfiles': ['_libs/src/util', + '_libs/tslibs/ccalendar', + '_libs/tslibs/timedeltas', + '_libs/tslibs/timezones', + '_libs/tslibs/nattype', + '_libs/tslibs/offsets'], + 'depends': tseries_depends + ['pandas/_libs/src/period_helper.h'], + 'sources': np_datetime_sources + ['pandas/_libs/src/period_helper.c']}, '_libs.tslibs.resolution': { 'pyxfile': '_libs/tslibs/resolution', 'pxdfiles': ['_libs/src/util',