Skip to content

Commit a557cef

Browse files
committed
Merge pull request #9291 from sinhrks/nano_add
BUG: Adding nano offset raises TypeError
2 parents 3fbc1ee + 89b3683 commit a557cef

File tree

7 files changed

+56
-9
lines changed

7 files changed

+56
-9
lines changed

doc/source/whatsnew/v0.16.0.txt

+3
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ Bug Fixes
152152

153153

154154

155+
- Bug in adding ``offsets.Nano`` to other offets raises ``TypeError`` (:issue:`9284`)
156+
157+
155158

156159

157160

Binary file not shown.

pandas/io/tests/test_pickle.py

+16
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ def read_pickles(self, version):
7575
if 'series' in data:
7676
if 'ts' in data['series']:
7777
self._validate_timeseries(data['series']['ts'], self.data['series']['ts'])
78+
self._validate_frequency(data['series']['ts'])
7879

7980
def test_read_pickles_0_10_1(self):
8081
self.read_pickles('0.10.1')
@@ -148,6 +149,21 @@ def _validate_timeseries(self, pickled, current):
148149
self.assertEqual(pickled.index.freq.normalize, False)
149150
self.assert_numpy_array_equal(pickled > 0, current > 0)
150151

152+
def _validate_frequency(self, pickled):
153+
# GH 9291
154+
from pandas.tseries.offsets import Day
155+
freq = pickled.index.freq
156+
result = freq + Day(1)
157+
self.assertTrue(result, Day(2))
158+
159+
result = freq + pandas.Timedelta(hours=1)
160+
self.assertTrue(isinstance(result, pandas.Timedelta))
161+
self.assertEqual(result, pandas.Timedelta(days=1, hours=1))
162+
163+
result = freq + pandas.Timedelta(nanoseconds=1)
164+
self.assertTrue(isinstance(result, pandas.Timedelta))
165+
self.assertEqual(result, pandas.Timedelta(days=1, nanoseconds=1))
166+
151167

152168
if __name__ == '__main__':
153169
import nose

pandas/tseries/offsets.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from dateutil.relativedelta import relativedelta, weekday
1010
from dateutil.easter import easter
1111
import pandas.tslib as tslib
12-
from pandas.tslib import Timestamp, OutOfBoundsDatetime
12+
from pandas.tslib import Timestamp, OutOfBoundsDatetime, Timedelta
1313

1414
import functools
1515

@@ -2010,7 +2010,7 @@ def f(self, other):
20102010

20112011

20122012
class Tick(SingleConstructorOffset):
2013-
_inc = timedelta(microseconds=1000)
2013+
_inc = Timedelta(microseconds=1000)
20142014

20152015
__gt__ = _tick_comp(operator.gt)
20162016
__ge__ = _tick_comp(operator.ge)
@@ -2107,36 +2107,37 @@ def _delta_to_tick(delta):
21072107

21082108

21092109
class Day(Tick):
2110-
_inc = timedelta(1)
2110+
_inc = Timedelta(days=1)
21112111
_prefix = 'D'
21122112

21132113

21142114
class Hour(Tick):
2115-
_inc = timedelta(0, 3600)
2115+
_inc = Timedelta(hours=1)
21162116
_prefix = 'H'
21172117

21182118

21192119
class Minute(Tick):
2120-
_inc = timedelta(0, 60)
2120+
_inc = Timedelta(minutes=1)
21212121
_prefix = 'T'
21222122

21232123

21242124
class Second(Tick):
2125-
_inc = timedelta(0, 1)
2125+
_inc = Timedelta(seconds=1)
21262126
_prefix = 'S'
21272127

21282128

21292129
class Milli(Tick):
2130+
_inc = Timedelta(milliseconds=1)
21302131
_prefix = 'L'
21312132

21322133

21332134
class Micro(Tick):
2134-
_inc = timedelta(microseconds=1)
2135+
_inc = Timedelta(microseconds=1)
21352136
_prefix = 'U'
21362137

21372138

21382139
class Nano(Tick):
2139-
_inc = np.timedelta64(1, 'ns')
2140+
_inc = Timedelta(nanoseconds=1)
21402141
_prefix = 'N'
21412142

21422143

pandas/tseries/tests/test_offsets.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import pandas.tseries.offsets as offsets
2626

2727
from pandas.io.pickle import read_pickle
28-
from pandas.tslib import NaT, Timestamp
28+
from pandas.tslib import NaT, Timestamp, Timedelta
2929
import pandas.tslib as tslib
3030
from pandas.util.testing import assertRaisesRegexp
3131
import pandas.util.testing as tm
@@ -2817,6 +2817,7 @@ def test_Easter():
28172817
assertEq(-Easter(), datetime(2010, 4, 4), datetime(2009, 4, 12))
28182818
assertEq(-Easter(2), datetime(2010, 4, 4), datetime(2008, 3, 23))
28192819

2820+
28202821
def test_Hour():
28212822
assertEq(Hour(), datetime(2010, 1, 1), datetime(2010, 1, 1, 1))
28222823
assertEq(Hour(-1), datetime(2010, 1, 1, 1), datetime(2010, 1, 1))
@@ -2904,6 +2905,10 @@ def test_Nanosecond():
29042905
assert (Nano(3) + Nano(2)) == Nano(5)
29052906
assert (Nano(3) - Nano(2)) == Nano()
29062907

2908+
# GH9284
2909+
assert Nano(1) + Nano(10) == Nano(11)
2910+
assert Nano(5) + Micro(1) == Nano(1005)
2911+
assert Micro(5) + Nano(1) == Nano(5001)
29072912

29082913
def test_tick_offset():
29092914
assert not Day().isAnchored()
@@ -2928,6 +2933,23 @@ def test_compare_ticks():
29282933
assert(kls(3) != kls(4))
29292934

29302935

2936+
class TestTicks(tm.TestCase):
2937+
2938+
def test_ticks(self):
2939+
offsets = [(Hour, Timedelta(hours=5)),
2940+
(Minute, Timedelta(hours=2, minutes=3)),
2941+
(Second, Timedelta(hours=2, seconds=3)),
2942+
(Milli, Timedelta(hours=2, milliseconds=3)),
2943+
(Micro, Timedelta(hours=2, microseconds=3)),
2944+
(Nano, Timedelta(hours=2, nanoseconds=3))]
2945+
2946+
for kls, expected in offsets:
2947+
offset = kls(3)
2948+
result = offset + Timedelta(hours=2)
2949+
self.assertTrue(isinstance(result, Timedelta))
2950+
self.assertEqual(result, expected)
2951+
2952+
29312953
class TestOffsetNames(tm.TestCase):
29322954
def test_get_offset_name(self):
29332955
assertRaisesRegexp(ValueError, 'Bad rule.*BusinessDays', get_offset_name, BDay(2))

pandas/tslib.pyx

+2
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,8 @@ cdef class _NaT(_Timestamp):
997997

998998

999999
def _delta_to_nanoseconds(delta):
1000+
if hasattr(delta, 'nanos'):
1001+
return delta.nanos
10001002
if hasattr(delta, 'delta'):
10011003
delta = delta.delta
10021004
if is_timedelta64_object(delta):

setup.py

+3
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,9 @@ def pxd(name):
590590
'tests/data/legacy_pickle/0.12.0/*.pickle',
591591
'tests/data/legacy_pickle/0.13.0/*.pickle',
592592
'tests/data/legacy_pickle/0.14.0/*.pickle',
593+
'tests/data/legacy_pickle/0.14.1/*.pickle',
594+
'tests/data/legacy_pickle/0.15.0/*.pickle',
595+
'tests/data/legacy_pickle/0.15.2/*.pickle',
593596
'tests/data/*.csv',
594597
'tests/data/*.dta',
595598
'tests/data/*.txt',

0 commit comments

Comments
 (0)