Skip to content

Commit 3e496ed

Browse files
committed
ENH: more nanosecond support #1238
1 parent 6c1f111 commit 3e496ed

File tree

5 files changed

+33
-13
lines changed

5 files changed

+33
-13
lines changed

doc/source/io.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ The two workhorse functions for reading text files (a.k.a. flat files) are
5959
They both use the same parsing code to intelligently convert tabular
6060
data into a DataFrame object. They can take a number of arguments:
6161

62-
- ``path_or_buffer``: Either a string path to a file, or any object with a
62+
- ``filepath_or_buffer``: Either a string path to a file, or any object with a
6363
``read`` method (such as an open file or ``StringIO``).
6464
- ``sep`` or ``delimiter``: A delimiter / separator to split fields
6565
on. `read_csv` is capable of inferring the delimiter automatically in some

pandas/core/generic.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def first(self, offset):
215215
end_date = end = self.index[0] + offset
216216

217217
# Tick-like, e.g. 3 weeks
218-
if not offset.isAnchored() and hasattr(offset, 'delta'):
218+
if not offset.isAnchored() and hasattr(offset, '_inc'):
219219
if end_date in self.index:
220220
end = self.index.searchsorted(end_date, side='left')
221221

pandas/src/datetime.pyx

+20-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ from cpython cimport *
99
from datetime cimport *
1010
from util cimport is_integer_object, is_datetime64_object
1111

12+
from datetime import timedelta
1213
from dateutil.parser import parse as parse_date
1314
cimport util
1415

@@ -240,7 +241,15 @@ cdef class _Timestamp(datetime):
240241
else:
241242
return Timestamp((self.offset.__mul__(other)).apply(self))
242243
else:
243-
return datetime.__add__(self, other)
244+
if isinstance(other, timedelta) or hasattr(other, 'delta'):
245+
nanos = _delta_to_nanoseconds(other)
246+
return Timestamp(self.value + nanos)
247+
else:
248+
result = datetime.__add__(self, other)
249+
if isinstance(result, datetime):
250+
result = Timestamp(result)
251+
result.nanosecond = self.nanosecond
252+
return result
244253

245254
def __sub__(self, other):
246255
if is_integer_object(other):
@@ -253,6 +262,16 @@ cdef class _Timestamp(datetime):
253262
field)
254263
return out[0]
255264

265+
def _delta_to_nanoseconds(delta):
266+
try:
267+
delta = delta.delta
268+
except:
269+
pass
270+
return (delta.days * 24 * 60 * 60 * 1000000
271+
+ delta.seconds * 1000000
272+
+ delta.microseconds) * 1000
273+
274+
256275
# lightweight C object to hold datetime & int64 pair
257276
cdef class _TSObject:
258277
cdef:

pandas/tseries/offsets.py

+7-10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from pandas.core.common import _count_not_none
66
from pandas.tseries.tools import to_datetime
7+
from pandas.util.decorators import cache_readonly
78

89
# import after tools, dateutil check
910
from dateutil.relativedelta import relativedelta
@@ -408,15 +409,15 @@ def __init__(self, n=1, **kwds):
408409
raise Exception('Day must be 0<=day<=6, got %d' %
409410
self.weekday)
410411

411-
self.delta = timedelta(weeks=1)
412+
self._inc = timedelta(weeks=1)
412413
self.kwds = kwds
413414

414415
def isAnchored(self):
415416
return (self.n == 1 and self.weekday is not None)
416417

417418
def apply(self, other):
418419
if self.weekday is None:
419-
return other + self.n * self.delta
420+
return other + self.n * self._inc
420421

421422
if self.n > 0:
422423
k = self.n
@@ -425,14 +426,14 @@ def apply(self, other):
425426
other = other + timedelta((self.weekday - otherDay) % 7)
426427
k = k - 1
427428
for i in xrange(k):
428-
other = other + self.delta
429+
other = other + self._inc
429430
else:
430431
k = self.n
431432
otherDay = other.weekday()
432433
if otherDay != self.weekday:
433434
other = other + timedelta((self.weekday - otherDay) % 7)
434435
for i in xrange(-k):
435-
other = other - self.delta
436+
other = other - self._inc
436437
return other
437438

438439
def onOffset(self, dt):
@@ -919,7 +920,6 @@ def rule_code(self):
919920
# Ticks
920921

921922
class Tick(DateOffset):
922-
_delta = None
923923
_inc = timedelta(microseconds=1000)
924924

925925
def __add__(self, other):
@@ -955,12 +955,9 @@ def __ne__(self, other):
955955
else:
956956
return DateOffset.__ne__(self, other)
957957

958-
@property
958+
@cache_readonly
959959
def delta(self):
960-
if self._delta is None:
961-
self._delta = self.n * self._inc
962-
963-
return self._delta
960+
return self.n * self._inc
964961

965962
@property
966963
def nanos(self):

pandas/tseries/tests/test_timeseries.py

+4
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,10 @@ def test_comparison(self):
11891189
self.assert_(other > val)
11901190
self.assert_(other >= val)
11911191

1192+
def test_delta_preserve_nanos(self):
1193+
val = Timestamp(1337299200000000123L)
1194+
result = val + timedelta(1)
1195+
self.assert_(result.nanosecond == val.nanosecond)
11921196

11931197
"""
11941198

0 commit comments

Comments
 (0)