@@ -17,8 +17,8 @@ cnp.import_array()
17
17
18
18
cimport pandas._libs.util as util
19
19
20
- from pandas._libs.tslibs.conversion cimport maybe_datetimelike_to_i8
21
20
from pandas._libs.tslibs.nattype cimport c_NaT as NaT
21
+ from pandas._libs.tslibs.c_timestamp cimport _Timestamp
22
22
23
23
from pandas._libs.hashtable cimport HashTable
24
24
@@ -407,20 +407,27 @@ cdef class DatetimeEngine(Int64Engine):
407
407
cdef _get_box_dtype(self ):
408
408
return ' M8[ns]'
409
409
410
+ cdef int64_t _unbox_scalar(self , scalar) except ? - 1 :
411
+ # NB: caller is responsible for ensuring tzawareness compat
412
+ # before we get here
413
+ if not (isinstance (scalar, _Timestamp) or scalar is NaT):
414
+ raise TypeError (scalar)
415
+ return scalar.value
416
+
410
417
def __contains__ (self , object val ):
411
418
cdef:
412
- int64_t loc
419
+ int64_t loc, conv
413
420
421
+ conv = self ._unbox_scalar(val)
414
422
if self .over_size_threshold and self .is_monotonic_increasing:
415
423
if not self .is_unique:
416
- return self ._get_loc_duplicates(val )
424
+ return self ._get_loc_duplicates(conv )
417
425
values = self ._get_index_values()
418
- conv = maybe_datetimelike_to_i8(val)
419
426
loc = values.searchsorted(conv, side = ' left' )
420
427
return values[loc] == conv
421
428
422
429
self ._ensure_mapping_populated()
423
- return maybe_datetimelike_to_i8(val) in self .mapping
430
+ return conv in self .mapping
424
431
425
432
cdef _get_index_values(self ):
426
433
return self .vgetter().view(' i8' )
@@ -429,45 +436,39 @@ cdef class DatetimeEngine(Int64Engine):
429
436
return algos.is_monotonic(values, timelike = True )
430
437
431
438
cpdef get_loc(self , object val):
439
+ # NB: the caller is responsible for ensuring that we are called
440
+ # with either a Timestamp or NaT (Timedelta or NaT for TimedeltaEngine)
441
+
432
442
cdef:
433
443
int64_t loc
434
444
if is_definitely_invalid_key(val):
435
445
raise TypeError
436
446
447
+ try :
448
+ conv = self ._unbox_scalar(val)
449
+ except TypeError :
450
+ raise KeyError (val)
451
+
437
452
# Welcome to the spaghetti factory
438
453
if self .over_size_threshold and self .is_monotonic_increasing:
439
454
if not self .is_unique:
440
- val = maybe_datetimelike_to_i8(val)
441
- return self ._get_loc_duplicates(val)
455
+ return self ._get_loc_duplicates(conv)
442
456
values = self ._get_index_values()
443
457
444
- try :
445
- conv = maybe_datetimelike_to_i8(val)
446
- loc = values.searchsorted(conv, side = ' left' )
447
- except TypeError :
448
- raise KeyError (val)
458
+ loc = values.searchsorted(conv, side = ' left' )
449
459
450
460
if loc == len (values) or values[loc] != conv:
451
461
raise KeyError (val)
452
462
return loc
453
463
454
464
self ._ensure_mapping_populated()
455
465
if not self .unique:
456
- val = maybe_datetimelike_to_i8(val)
457
- return self ._get_loc_duplicates(val)
466
+ return self ._get_loc_duplicates(conv)
458
467
459
468
try :
460
- return self .mapping.get_item(val.value )
469
+ return self .mapping.get_item(conv )
461
470
except KeyError :
462
471
raise KeyError (val)
463
- except AttributeError :
464
- pass
465
-
466
- try :
467
- val = maybe_datetimelike_to_i8(val)
468
- return self .mapping.get_item(val)
469
- except (TypeError , ValueError ):
470
- raise KeyError (val)
471
472
472
473
def get_indexer (self , values ):
473
474
self ._ensure_mapping_populated()
@@ -494,6 +495,11 @@ cdef class TimedeltaEngine(DatetimeEngine):
494
495
cdef _get_box_dtype(self ):
495
496
return ' m8[ns]'
496
497
498
+ cdef int64_t _unbox_scalar(self , scalar) except ? - 1 :
499
+ if not (isinstance (scalar, Timedelta) or scalar is NaT):
500
+ raise TypeError (scalar)
501
+ return scalar.value
502
+
497
503
498
504
cdef class PeriodEngine(Int64Engine):
499
505
0 commit comments