BUG: segfault manifesting with dateutil=2.6 w.r.t. replace when timez… · pandas-dev/pandas@f8bd08e (original) (raw)
`@@ -98,6 +98,7 @@ except NameError: # py3
`
98
98
`cdef inline object create_timestamp_from_ts(
`
99
99
` int64_t value, pandas_datetimestruct dts,
`
100
100
`object tz, object freq):
`
``
101
`+
""" convenience routine to construct a Timestamp from its parts """
`
101
102
` cdef _Timestamp ts_base
`
102
103
` ts_base = _Timestamp.new(Timestamp, dts.year, dts.month,
`
103
104
` dts.day, dts.hour, dts.min,
`
`@@ -112,6 +113,7 @@ cdef inline object create_timestamp_from_ts(
`
112
113
`cdef inline object create_datetime_from_ts(
`
113
114
` int64_t value, pandas_datetimestruct dts,
`
114
115
`object tz, object freq):
`
``
116
`+
""" convenience routine to construct a datetime.datetime from its parts """
`
115
117
`return datetime(dts.year, dts.month, dts.day, dts.hour,
`
116
118
` dts.min, dts.sec, dts.us, tz)
`
117
119
``
`@@ -378,7 +380,6 @@ class Timestamp(_Timestamp):
`
378
380
`# Mixing pydatetime positional and keyword arguments is forbidden!
`
379
381
``
380
382
` cdef _TSObject ts
`
381
``
`-
cdef _Timestamp ts_base
`
382
383
``
383
384
`if offset is not None:
`
384
385
`# deprecate offset kwd in 0.19.0, GH13593
`
`@@ -412,17 +413,7 @@ class Timestamp(_Timestamp):
`
412
413
`from pandas.tseries.frequencies import to_offset
`
413
414
` freq = to_offset(freq)
`
414
415
``
415
``
`-
make datetime happy
`
416
``
`-
ts_base = _Timestamp.new(cls, ts.dts.year, ts.dts.month,
`
417
``
`-
ts.dts.day, ts.dts.hour, ts.dts.min,
`
418
``
`-
ts.dts.sec, ts.dts.us, ts.tzinfo)
`
419
``
-
420
``
`-
fill out rest of data
`
421
``
`-
ts_base.value = ts.value
`
422
``
`-
ts_base.freq = freq
`
423
``
`-
ts_base.nanosecond = ts.dts.ps / 1000
`
424
``
-
425
``
`-
return ts_base
`
``
416
`+
return create_timestamp_from_ts(ts.value, ts.dts, ts.tzinfo, freq)
`
426
417
``
427
418
`def _round(self, freq, rounder):
`
428
419
``
`@@ -660,8 +651,80 @@ class Timestamp(_Timestamp):
`
660
651
` astimezone = tz_convert
`
661
652
``
662
653
`def replace(self, **kwds):
`
663
``
`-
return Timestamp(datetime.replace(self, **kwds),
`
664
``
`-
freq=self.freq)
`
``
654
`+
"""
`
``
655
`+
implements datetime.replace, handles nanoseconds
`
``
656
+
``
657
`+
Parameters
`
``
658
`+
`
``
659
`+
kwargs: key-value dict
`
``
660
+
``
661
`+
accepted keywords are:
`
``
662
`+
year, month, day, hour, minute, second, microsecond, nanosecond, tzinfo
`
``
663
+
``
664
`+
values must be integer, or for tzinfo, a tz-convertible
`
``
665
+
``
666
`+
Returns
`
``
667
`+
`
``
668
`+
Timestamp with fields replaced
`
``
669
`+
"""
`
``
670
+
``
671
`+
cdef:
`
``
672
`+
pandas_datetimestruct dts
`
``
673
`+
int64_t value
`
``
674
`+
object tzinfo, result, k, v
`
``
675
`+
_TSObject ts
`
``
676
+
``
677
`+
set to naive if needed
`
``
678
`+
tzinfo = self.tzinfo
`
``
679
`+
value = self.value
`
``
680
`+
if tzinfo is not None:
`
``
681
`+
value = tz_convert_single(value, 'UTC', tzinfo)
`
``
682
+
``
683
`+
setup components
`
``
684
`+
pandas_datetime_to_datetimestruct(value, PANDAS_FR_ns, &dts)
`
``
685
`+
dts.ps = self.nanosecond * 1000
`
``
686
+
``
687
`+
replace
`
``
688
`+
def validate(k, v):
`
``
689
`+
""" validate integers """
`
``
690
`+
if not isinstance(v, int):
`
``
691
`+
raise ValueError("value must be an integer, received {v} for {k}".format(v=type(v), k=k))
`
``
692
`+
return v
`
``
693
+
``
694
`+
for k, v in kwds.items():
`
``
695
`+
if k == 'year':
`
``
696
`+
dts.year = validate(k, v)
`
``
697
`+
elif k == 'month':
`
``
698
`+
dts.month = validate(k, v)
`
``
699
`+
elif k == 'day':
`
``
700
`+
dts.day = validate(k, v)
`
``
701
`+
elif k == 'hour':
`
``
702
`+
dts.hour = validate(k, v)
`
``
703
`+
elif k == 'minute':
`
``
704
`+
dts.min = validate(k, v)
`
``
705
`+
elif k == 'second':
`
``
706
`+
dts.sec = validate(k, v)
`
``
707
`+
elif k == 'microsecond':
`
``
708
`+
dts.us = validate(k, v)
`
``
709
`+
elif k == 'nanosecond':
`
``
710
`+
dts.ps = validate(k, v) * 1000
`
``
711
`+
elif k == 'tzinfo':
`
``
712
`+
tzinfo = v
`
``
713
`+
else:
`
``
714
`+
raise ValueError("invalid name {} passed".format(k))
`
``
715
+
``
716
`+
reconstruct & check bounds
`
``
717
`+
value = pandas_datetimestruct_to_datetime(PANDAS_FR_ns, &dts)
`
``
718
`+
if value != NPY_NAT:
`
``
719
`+
_check_dts_bounds(&dts)
`
``
720
+
``
721
`+
set tz if needed
`
``
722
`+
if tzinfo is not None:
`
``
723
`+
value = tz_convert_single(value, tzinfo, 'UTC')
`
``
724
+
``
725
`+
result = create_timestamp_from_ts(value, dts, tzinfo, self.freq)
`
``
726
+
``
727
`+
return result
`
665
728
``
666
729
`def isoformat(self, sep='T'):
`
667
730
` base = super(_Timestamp, self).isoformat(sep=sep)
`
`@@ -5041,7 +5104,9 @@ cpdef normalize_date(object dt):
`
5041
5104
` -------
`
5042
5105
` normalized : datetime.datetime or Timestamp
`
5043
5106
`"""
`
5044
``
`-
if PyDateTime_Check(dt):
`
``
5107
`+
if is_timestamp(dt):
`
``
5108
`+
return dt.replace(hour=0, minute=0, second=0, microsecond=0, nanosecond=0)
`
``
5109
`+
elif PyDateTime_Check(dt):
`
5045
5110
`return dt.replace(hour=0, minute=0, second=0, microsecond=0)
`
5046
5111
`elif PyDate_Check(dt):
`
5047
5112
`return datetime(dt.year, dt.month, dt.day)
`