@@ -30,7 +30,7 @@ from util cimport (is_integer_object, is_float_object, is_datetime64_object,
30
30
is_timedelta64_object, INT64_MAX)
31
31
cimport util
32
32
33
- from cpython.datetime cimport PyTZInfo_Check
33
+ from cpython.datetime cimport PyDelta_Check, PyTZInfo_Check
34
34
# this is our datetime.pxd
35
35
from datetime cimport (
36
36
pandas_datetimestruct,
@@ -50,7 +50,6 @@ from datetime cimport (
50
50
check_dts_bounds,
51
51
PANDAS_FR_ns,
52
52
PyDateTime_Check, PyDate_Check,
53
- PyDelta_Check, # PyDelta_Check(x) --> isinstance(x, timedelta)
54
53
PyDateTime_IMPORT,
55
54
timedelta, datetime
56
55
)
@@ -840,6 +839,7 @@ class NaTType(_NaT):
840
839
841
840
base = _NaT.__new__ (cls , 1 , 1 , 1 )
842
841
base.value = NPY_NAT
842
+ base.freq = None
843
843
844
844
return base
845
845
@@ -862,6 +862,12 @@ class NaTType(_NaT):
862
862
def __long__ (self ):
863
863
return NPY_NAT
864
864
865
+ def __reduce_ex__ (self , protocol ):
866
+ # python 3.6 compat
867
+ # http://bugs.python.org/issue28730
868
+ # now __reduce_ex__ is defined and higher priority than __reduce__
869
+ return self .__reduce__()
870
+
865
871
def __reduce__ (self ):
866
872
return (__nat_unpickle, (None , ))
867
873
@@ -997,6 +1003,16 @@ class NaTType(_NaT):
997
1003
tz_localize = _make_nat_func(' tz_localize' , Timestamp)
998
1004
replace = _make_nat_func(' replace' , Timestamp)
999
1005
1006
+ def to_datetime (self ):
1007
+ """
1008
+ DEPRECATED: use :meth:`to_pydatetime` instead.
1009
+
1010
+ Convert a Timestamp object to a native Python datetime object.
1011
+ """
1012
+ warnings.warn(" to_datetime is deprecated. Use self.to_pydatetime()" ,
1013
+ FutureWarning , stacklevel = 2 )
1014
+ return self .to_pydatetime(warn = False )
1015
+
1000
1016
1001
1017
def __nat_unpickle (*args ):
1002
1018
# return constant defined in the module
@@ -1143,9 +1159,9 @@ cdef class _Timestamp(datetime):
1143
1159
int ndim
1144
1160
1145
1161
if isinstance (other, _Timestamp):
1146
- if other is NaT:
1147
- return _cmp_nat_dt(other, self , _reverse_ops[op])
1148
1162
ots = other
1163
+ elif other is NaT:
1164
+ return _cmp_nat_dt(other, self , _reverse_ops[op])
1149
1165
elif PyDateTime_Check(other):
1150
1166
if self .nanosecond == 0 :
1151
1167
val = self .to_pydatetime()
@@ -1448,8 +1464,7 @@ _nat_scalar_rules[Py_GE] = False
1448
1464
1449
1465
1450
1466
cdef _nat_divide_op(self , other):
1451
- if (PyDelta_Check(other) or
1452
- is_timedelta64_object(other) or other is NaT):
1467
+ if PyDelta_Check(other) or is_timedelta64_object(other) or other is NaT:
1453
1468
return np.nan
1454
1469
if is_integer_object(other) or is_float_object(other):
1455
1470
return NaT
@@ -1461,7 +1476,10 @@ cdef _nat_rdivide_op(self, other):
1461
1476
return NotImplemented
1462
1477
1463
1478
1464
- cdef class _NaT(_Timestamp):
1479
+ cdef class _NaT(datetime):
1480
+ cdef readonly:
1481
+ int64_t value
1482
+ object freq
1465
1483
1466
1484
def __hash__ (_NaT self ):
1467
1485
# py3k needs this defined here
@@ -1475,34 +1493,52 @@ cdef class _NaT(_Timestamp):
1475
1493
1476
1494
if ndim == 0 :
1477
1495
if is_datetime64_object(other):
1478
- other = Timestamp(other)
1496
+ return _nat_scalar_rules[op]
1479
1497
else :
1480
1498
raise TypeError (' Cannot compare type %r with type %r ' %
1481
1499
(type (self ).__name__, type (other).__name__))
1482
1500
return PyObject_RichCompare(other, self , _reverse_ops[op])
1483
1501
1484
1502
def __add__ (self , other ):
1485
- try :
1486
- if PyDateTime_Check(other):
1487
- return NaT
1488
- result = _Timestamp.__add__ (self , other)
1489
- # Timestamp.__add__ doesn't return DatetimeIndex/TimedeltaIndex
1490
- if result is NotImplemented :
1491
- return result
1492
- except (OverflowError , OutOfBoundsDatetime):
1493
- pass
1503
+ if PyDateTime_Check(other):
1504
+ return NaT
1505
+
1506
+ elif hasattr (other, ' delta' ):
1507
+ # Timedelta, offsets.Tick, offsets.Week
1508
+ return NaT
1509
+ elif getattr (other, ' _typ' , None ) in [' dateoffset' , ' series' ,
1510
+ ' period' , ' datetimeindex' ,
1511
+ ' timedeltaindex' ]:
1512
+ # Duplicate logic in _Timestamp.__add__ to avoid needing
1513
+ # to subclass; allows us to @final(_Timestamp.__add__)
1514
+ return NotImplemented
1494
1515
return NaT
1495
1516
1496
1517
def __sub__ (self , other ):
1497
- if PyDateTime_Check(other) or PyDelta_Check(other):
1518
+ # Duplicate some logic from _Timestamp.__sub__ to avoid needing
1519
+ # to subclass; allows us to @final(_Timestamp.__sub__)
1520
+ if PyDateTime_Check(other):
1521
+ return NaT
1522
+ elif PyDelta_Check(other):
1498
1523
return NaT
1499
- try :
1500
- result = _Timestamp.__sub__ (self , other)
1501
- # Timestamp.__sub__ may return DatetimeIndex/TimedeltaIndex
1502
- if result is NotImplemented or hasattr (result, ' _typ' ):
1503
- return result
1504
- except (OverflowError , OutOfBoundsDatetime):
1505
- pass
1524
+
1525
+ elif getattr (other, ' _typ' , None ) == ' datetimeindex' :
1526
+ # a Timestamp-DatetimeIndex -> yields a negative TimedeltaIndex
1527
+ return - other.__sub__ (self )
1528
+
1529
+ elif getattr (other, ' _typ' , None ) == ' timedeltaindex' :
1530
+ # a Timestamp-TimedeltaIndex -> yields a negative TimedeltaIndex
1531
+ return (- other).__add__(self )
1532
+
1533
+ elif hasattr (other, ' delta' ):
1534
+ # offsets.Tick, offsets.Week
1535
+ neg_other = - other
1536
+ return self + neg_other
1537
+
1538
+ elif getattr (other, ' _typ' , None ) in [' period' ,
1539
+ ' periodindex' , ' dateoffset' ]:
1540
+ return NotImplemented
1541
+
1506
1542
return NaT
1507
1543
1508
1544
def __pos__ (self ):
@@ -1525,6 +1561,14 @@ cdef class _NaT(_Timestamp):
1525
1561
return NaT
1526
1562
return NotImplemented
1527
1563
1564
+ @property
1565
+ def asm8 (self ):
1566
+ return np.datetime64(NPY_NAT, ' ns' )
1567
+
1568
+ def to_datetime64 (self ):
1569
+ """ Returns a numpy.datetime64 object with 'ns' precision """
1570
+ return np.datetime64(' NaT' )
1571
+
1528
1572
1529
1573
# lightweight C object to hold datetime & int64 pair
1530
1574
cdef class _TSObject:
0 commit comments