Skip to content

Commit c34e438

Browse files
committed
easy parts of pandas-dev#23368
1 parent 93aba79 commit c34e438

10 files changed

+59
-43
lines changed

pandas/_libs/missing.pxd

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# -*- coding: utf-8 -*-
22

3-
from tslibs.nattype cimport is_null_datetimelike
4-
53
cpdef bint checknull(object val)
64
cpdef bint checknull_old(object val)
75

pandas/_libs/tslibs/conversion.pyx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ TD_DTYPE = np.dtype('m8[ns]')
4949

5050
UTC = pytz.UTC
5151

52+
5253
# ----------------------------------------------------------------------
5354
# Misc Helpers
5455

55-
# TODO: How to declare np.datetime64 as the input type?
5656
cdef inline int64_t get_datetime64_nanos(object val) except? -1:
5757
"""
5858
Extract the value and unit from a np.datetime64 object, then convert the
@@ -74,6 +74,8 @@ cdef inline int64_t get_datetime64_nanos(object val) except? -1:
7474
return ival
7575

7676

77+
@cython.boundscheck(False)
78+
@cython.wraparound(False)
7779
def ensure_datetime64ns(ndarray arr, copy=True):
7880
"""
7981
Ensure a np.datetime64 array has dtype specifically 'datetime64[ns]'
@@ -138,18 +140,20 @@ def ensure_timedelta64ns(ndarray arr, copy=True):
138140
return arr.astype(TD_DTYPE, copy=copy)
139141

140142

143+
@cython.boundscheck(False)
144+
@cython.wraparound(False)
141145
def datetime_to_datetime64(object[:] values):
142146
"""
143147
Convert ndarray of datetime-like objects to int64 array representing
144148
nanosecond timestamps.
145149
146150
Parameters
147151
----------
148-
values : ndarray
152+
values : ndarray[object]
149153
150154
Returns
151155
-------
152-
result : ndarray with dtype int64
156+
result : ndarray[int64_t]
153157
inferred_tz : tzinfo or None
154158
"""
155159
cdef:
@@ -225,6 +229,7 @@ cdef class _TSObject:
225229

226230
@property
227231
def value(self):
232+
# This is needed in order for `value` to be accessible in lib.pyx
228233
return self.value
229234

230235

@@ -756,6 +761,8 @@ cpdef int64_t tz_convert_single(int64_t val, object tz1, object tz2):
756761
return _tz_convert_dst(arr, tz2, to_utc=False)[0]
757762

758763

764+
@cython.boundscheck(False)
765+
@cython.wraparound(False)
759766
cdef inline int64_t[:] _tz_convert_one_way(int64_t[:] vals, object tz,
760767
bint to_utc):
761768
"""
@@ -1051,7 +1058,7 @@ cdef inline str _render_tstamp(int64_t val):
10511058
# Normalization
10521059

10531060

1054-
def normalize_date(object dt):
1061+
def normalize_date(dt: object) -> datetime:
10551062
"""
10561063
Normalize datetime.datetime value to midnight. Returns datetime.date as a
10571064
datetime.datetime at midnight
@@ -1085,7 +1092,7 @@ def normalize_date(object dt):
10851092

10861093
@cython.wraparound(False)
10871094
@cython.boundscheck(False)
1088-
def normalize_i8_timestamps(int64_t[:] stamps, tz=None):
1095+
def normalize_i8_timestamps(int64_t[:] stamps, object tz=None):
10891096
"""
10901097
Normalize each of the (nanosecond) timestamps in the given array by
10911098
rounding down to the beginning of the day (i.e. midnight). If `tz`
@@ -1122,7 +1129,7 @@ def normalize_i8_timestamps(int64_t[:] stamps, tz=None):
11221129

11231130
@cython.wraparound(False)
11241131
@cython.boundscheck(False)
1125-
cdef int64_t[:] _normalize_local(int64_t[:] stamps, object tz):
1132+
cdef int64_t[:] _normalize_local(int64_t[:] stamps, tzinfo tz):
11261133
"""
11271134
Normalize each of the (nanosecond) timestamps in the given array by
11281135
rounding down to the beginning of the day (i.e. midnight) for the
@@ -1131,7 +1138,7 @@ cdef int64_t[:] _normalize_local(int64_t[:] stamps, object tz):
11311138
Parameters
11321139
----------
11331140
stamps : int64 ndarray
1134-
tz : tzinfo or None
1141+
tz : tzinfo
11351142
11361143
Returns
11371144
-------
@@ -1207,6 +1214,8 @@ cdef inline int64_t _normalized_stamp(npy_datetimestruct *dts) nogil:
12071214
return dtstruct_to_dt64(dts)
12081215

12091216

1217+
@cython.wraparound(False)
1218+
@cython.boundscheck(False)
12101219
def is_date_array_normalized(int64_t[:] stamps, tz=None):
12111220
"""
12121221
Check if all of the given (nanosecond) timestamps are normalized to

pandas/_libs/tslibs/fields.pyx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ def get_time_micros(ndarray[int64_t] dtindex):
4040
return micros
4141

4242

43+
@cython.wraparound(False)
44+
@cython.boundscheck(False)
4345
def build_field_sarray(int64_t[:] dtindex):
4446
"""
4547
Datetime as int64 representation to a structured array of fields

pandas/_libs/tslibs/nattype.pyx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ cdef class _NaT(datetime):
9797
return hash(self.value)
9898

9999
def __richcmp__(_NaT self, object other, int op):
100-
cdef int ndim = getattr(other, 'ndim', -1)
100+
cdef:
101+
int ndim = getattr(other, 'ndim', -1)
101102

102103
if ndim == -1:
103104
return _nat_scalar_rules[op]
@@ -181,7 +182,7 @@ cdef class _NaT(datetime):
181182

182183
def to_datetime64(self):
183184
""" Returns a numpy.datetime64 object with 'ns' precision """
184-
return np.datetime64('NaT')
185+
return np.datetime64('NaT', 'ns')
185186

186187

187188
class NaTType(_NaT):

pandas/_libs/tslibs/np_datetime.pyx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ cdef inline void dt64_to_dtstruct(int64_t dt64,
136136
pandas_datetime_to_datetimestruct(dt64, NPY_FR_ns, out)
137137
return
138138

139+
139140
cdef inline void td64_to_tdstruct(int64_t td64,
140141
pandas_timedeltastruct* out) nogil:
141142
"""Convenience function to call pandas_timedelta_to_timedeltastruct

pandas/_libs/tslibs/offsets.pyx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ from cython import Py_ssize_t
55

66
import time
77
from cpython.datetime cimport (PyDateTime_IMPORT,
8+
PyDateTime_Check,
89
datetime, timedelta,
910
time as dt_time)
1011
PyDateTime_IMPORT
@@ -354,7 +355,7 @@ class _BaseOffset(object):
354355
return NotImplemented
355356

356357
def __sub__(self, other):
357-
if isinstance(other, datetime):
358+
if PyDateTime_Check(other):
358359
raise TypeError('Cannot subtract datetime from offset.')
359360
elif type(other) == type(self):
360361
return type(self)(self.n - other.n, normalize=self.normalize,
@@ -496,7 +497,7 @@ class _Tick(object):
496497
# ----------------------------------------------------------------------
497498
# RelativeDelta Arithmetic
498499

499-
cpdef datetime shift_day(datetime other, int days):
500+
def shift_day(other: datetime, days: int) -> datetime:
500501
"""
501502
Increment the datetime `other` by the given number of days, retaining
502503
the time-portion of the datetime. For tz-naive datetimes this is
@@ -988,8 +989,7 @@ cpdef int roll_qtrday(datetime other, int n, int month, object day_opt,
988989
return n
989990

990991

991-
cpdef int roll_yearday(datetime other, int n, int month,
992-
object day_opt) except? -1:
992+
def roll_yearday(other: datetime, n: int, month: int, day_opt: object) -> int:
993993
"""
994994
Possibly increment or decrement the number of periods to shift
995995
based on rollforward/rollbackward conventions.

pandas/_libs/tslibs/parsing.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ cdef dateutil_parse(object timestr, object default, ignoretz=False,
361361
return ret, reso
362362

363363

364-
cpdef object _get_rule_month(object source, object default='DEC'):
364+
cdef object _get_rule_month(object source, object default='DEC'):
365365
"""
366366
Return starting month of given freq, default is December.
367367

pandas/_libs/tslibs/period.pyx

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from datetime import datetime, date
33

44
from cpython cimport (
5-
PyUnicode_Check,
65
PyObject_RichCompareBool,
76
Py_EQ, Py_NE)
87

@@ -14,9 +13,9 @@ from libc.stdlib cimport free, malloc
1413
from libc.time cimport strftime, tm
1514
from libc.string cimport strlen, memset
1615

17-
cimport cython
16+
import cython
1817

19-
from cpython.datetime cimport (PyDateTime_Check, PyDelta_Check,
18+
from cpython.datetime cimport (PyDateTime_Check, PyDelta_Check, PyDate_Check,
2019
PyDateTime_IMPORT)
2120
# import datetime C API
2221
PyDateTime_IMPORT
@@ -47,7 +46,7 @@ from frequencies cimport (get_freq_code, get_base_alias,
4746
get_rule_month)
4847
from parsing import parse_time_string
4948
from resolution import Resolution
50-
from nattype import nat_strings, NaT, iNaT
49+
from nattype import nat_strings, NaT
5150
from nattype cimport _nat_scalar_rules, NPY_NAT, is_null_datetimelike
5251
from offsets cimport to_offset
5352
from offsets import _Tick
@@ -307,6 +306,7 @@ cdef inline int64_t transform_via_day(int64_t ordinal,
307306
result = second_func(result, af_info)
308307
return result
309308

309+
310310
# --------------------------------------------------------------------
311311
# Conversion _to_ Daily Freq
312312

@@ -551,7 +551,7 @@ cdef int64_t asfreq_AtoA(int64_t ordinal, asfreq_info *af_info):
551551
cdef int64_t asfreq_AtoQ(int64_t ordinal, asfreq_info *af_info):
552552
return transform_via_day(ordinal, af_info,
553553
<freq_conv_func>asfreq_AtoDT,
554-
<freq_conv_func>asfreq_DTtoQ);
554+
<freq_conv_func>asfreq_DTtoQ)
555555

556556

557557
cdef int64_t asfreq_AtoM(int64_t ordinal, asfreq_info *af_info):
@@ -976,7 +976,6 @@ cdef inline int month_to_quarter(int month):
976976
# ----------------------------------------------------------------------
977977
# Period logic
978978

979-
980979
@cython.wraparound(False)
981980
@cython.boundscheck(False)
982981
def dt64arr_to_periodarr(int64_t[:] dtarr, int freq, tz=None):
@@ -1041,8 +1040,8 @@ cpdef int64_t period_asfreq(int64_t ordinal, int freq1, int freq2, bint end):
10411040
freq_conv_func func
10421041
asfreq_info af_info
10431042

1044-
if ordinal == iNaT:
1045-
return iNaT
1043+
if ordinal == NPY_NAT:
1044+
return NPY_NAT
10461045

10471046
func = get_asfreq_func(freq1, freq2)
10481047
get_asfreq_info(freq1, freq2, end, &af_info)
@@ -1106,6 +1105,8 @@ cdef inline int calc_week_end(int freq, int group) nogil:
11061105
return freq - group
11071106

11081107

1108+
@cython.wraparound(False)
1109+
@cython.boundscheck(False)
11091110
def period_asfreq_arr(ndarray[int64_t] arr, int freq1, int freq2, bint end):
11101111
"""
11111112
Convert int64-array of period ordinals from one frequency to another, and
@@ -1124,11 +1125,11 @@ def period_asfreq_arr(ndarray[int64_t] arr, int freq1, int freq2, bint end):
11241125
func = get_asfreq_func(freq1, freq2)
11251126
get_asfreq_info(freq1, freq2, end, &af_info)
11261127

1127-
mask = arr == iNaT
1128+
mask = arr == NPY_NAT
11281129
if mask.any(): # NaT process
11291130
for i in range(n):
11301131
val = arr[i]
1131-
if val != iNaT:
1132+
if val != NPY_NAT:
11321133
val = func(val, &af_info)
11331134
if val == INT32_MIN:
11341135
raise ValueError("Unable to convert to desired frequency.")
@@ -1192,7 +1193,7 @@ def period_format(int64_t value, int freq, object fmt=None):
11921193
cdef:
11931194
int freq_group
11941195

1195-
if value == iNaT:
1196+
if value == NPY_NAT:
11961197
return repr(NaT)
11971198

11981199
if fmt is None:
@@ -1248,7 +1249,7 @@ cdef object _period_strftime(int64_t value, int freq, object fmt):
12481249
list found_pat = [False] * len(extra_fmts)
12491250
int year, quarter
12501251

1251-
if PyUnicode_Check(fmt):
1252+
if isinstance(fmt, unicode):
12521253
fmt = fmt.encode('utf-8')
12531254

12541255
get_date_info(value, freq, &dts)
@@ -1381,6 +1382,8 @@ cdef int pdays_in_month(int64_t ordinal, int freq):
13811382
return ccalendar.get_days_in_month(dts.year, dts.month)
13821383

13831384

1385+
@cython.wraparound(False)
1386+
@cython.boundscheck(False)
13841387
def get_period_field_arr(int code, int64_t[:] arr, int freq):
13851388
cdef:
13861389
Py_ssize_t i, sz
@@ -1395,7 +1398,7 @@ def get_period_field_arr(int code, int64_t[:] arr, int freq):
13951398
out = np.empty(sz, dtype=np.int64)
13961399

13971400
for i in range(sz):
1398-
if arr[i] == iNaT:
1401+
if arr[i] == NPY_NAT:
13991402
out[i] = -1
14001403
continue
14011404
out[i] = func(arr[i], freq)
@@ -1431,6 +1434,8 @@ cdef accessor _get_accessor_func(int code):
14311434
return NULL
14321435

14331436

1437+
@cython.wraparound(False)
1438+
@cython.boundscheck(False)
14341439
def extract_ordinals(object[:] values, freq):
14351440
cdef:
14361441
Py_ssize_t i, n = len(values)
@@ -1443,7 +1448,7 @@ def extract_ordinals(object[:] values, freq):
14431448
p = values[i]
14441449

14451450
if is_null_datetimelike(p):
1446-
ordinals[i] = iNaT
1451+
ordinals[i] = NPY_NAT
14471452
else:
14481453
try:
14491454
ordinals[i] = p.ordinal
@@ -1456,7 +1461,7 @@ def extract_ordinals(object[:] values, freq):
14561461
p = Period(p, freq=freq)
14571462
if p is NaT:
14581463
# input may contain NaT-like string
1459-
ordinals[i] = iNaT
1464+
ordinals[i] = NPY_NAT
14601465
else:
14611466
ordinals[i] = p.ordinal
14621467

@@ -1581,7 +1586,7 @@ cdef class _Period(object):
15811586
"""
15821587
Fast creation from an ordinal and freq that are already validated!
15831588
"""
1584-
if ordinal == iNaT:
1589+
if ordinal == NPY_NAT:
15851590
return NaT
15861591
else:
15871592
freq = cls._maybe_convert_freq(freq)
@@ -2420,7 +2425,7 @@ class Period(_Period):
24202425
if (year is None and month is None and
24212426
quarter is None and day is None and
24222427
hour is None and minute is None and second is None):
2423-
ordinal = iNaT
2428+
ordinal = NPY_NAT
24242429
else:
24252430
if freq is None:
24262431
raise ValueError("If value is None, freq cannot be None")
@@ -2446,15 +2451,15 @@ class Period(_Period):
24462451
ordinal = converted.ordinal
24472452

24482453
elif is_null_datetimelike(value) or value in nat_strings:
2449-
ordinal = iNaT
2454+
ordinal = NPY_NAT
24502455

24512456
elif is_string_object(value) or util.is_integer_object(value):
24522457
if util.is_integer_object(value):
24532458
value = str(value)
24542459
value = value.upper()
24552460
dt, _, reso = parse_time_string(value, freq)
24562461
if dt is NaT:
2457-
ordinal = iNaT
2462+
ordinal = NPY_NAT
24582463

24592464
if freq is None:
24602465
try:
@@ -2464,15 +2469,15 @@ class Period(_Period):
24642469
"Invalid frequency or could not infer: {reso}"
24652470
.format(reso=reso))
24662471

2467-
elif isinstance(value, datetime):
2472+
elif PyDateTime_Check(value):
24682473
dt = value
24692474
if freq is None:
24702475
raise ValueError('Must supply freq for datetime value')
24712476
elif util.is_datetime64_object(value):
24722477
dt = Timestamp(value)
24732478
if freq is None:
24742479
raise ValueError('Must supply freq for datetime value')
2475-
elif isinstance(value, date):
2480+
elif PyDate_Check(value):
24762481
dt = datetime(year=value.year, month=value.month, day=value.day)
24772482
if freq is None:
24782483
raise ValueError('Must supply freq for datetime value')

0 commit comments

Comments
 (0)