Repository: pandas-dev/pandas

Issue:
BUG: Period ops with np.timedelta64 cause unexpected result
`Period` + `np.timedelta64` doesn't raise `TypeError(NotImplemented)` (like `offsets` does), and results in erratic internal representation.

```
import pandas as pd
import numpy as np

p = pd.Period('2011-01-01', freq='D')
p = p + np.timedelta64(2, 'h')
# This raises no error

print(p)
# TypeError: don't know how to convert scalar number to int

p.ordinal
#14977 hours
```

`PeriodIndex` + `np.timedelta64` also doesn't raise `TypeError(NotImplemented)`, and are added ignoring `PeriodIndex.freq`.

```
pidx = pd.period_range('2011-01-01', freq='D', periods=5)
pidx = pidx + np.timedelta64(2, 'h')
pidx
# <class 'pandas.tseries.period.PeriodIndex'>
# [2011-01-03, ..., 2011-01-07]
# Length: 5, Freq: D
```



Discussion:
Related to #5202.


Resolving patch:
diff --git a/pandas/tseries/period.py b/pandas/tseries/period.py
--- a/pandas/tseries/period.py
+++ b/pandas/tseries/period.py
@@ -1,7 +1,7 @@
 # pylint: disable=E1101,E1103,W0232
 import operator
 
-from datetime import datetime, date
+from datetime import datetime, date, timedelta
 import numpy as np
 from pandas.core.base import PandasObject
 
@@ -10,6 +10,7 @@
 from pandas.tseries.index import DatetimeIndex, Int64Index, Index
 from pandas.core.base import DatetimeIndexOpsMixin
 from pandas.tseries.tools import parse_time_string
+import pandas.tseries.offsets as offsets
 
 import pandas.core.common as com
 from pandas.core.common import (isnull, _INT64_DTYPE, _maybe_box,
@@ -169,8 +170,37 @@ def __ne__(self, other):
     def __hash__(self):
         return hash((self.ordinal, self.freq))
 
+    def _add_delta(self, other):
+        if isinstance(other, (timedelta, np.timedelta64, offsets.Tick)):
+            offset = frequencies.to_offset(self.freq)
+            if isinstance(offset, offsets.Tick):
+                nanos = tslib._delta_to_nanoseconds(other)
+                offset_nanos = tslib._delta_to_nanoseconds(offset)
+
+                if nanos % offset_nanos == 0:
+                    if self.ordinal == tslib.iNaT:
+                        ordinal = self.ordinal
+                    else:
+                        ordinal = self.ordinal + (nanos // offset_nanos)
+                    return Period(ordinal=ordinal, freq=self.freq)
+        elif isinstance(other, offsets.DateOffset):
+            freqstr = frequencies.get_standard_freq(other)
+            base = frequencies.get_base_alias(freqstr)
+
+            if base == self.freq:
+                if self.ordinal == tslib.iNaT:
+                    ordinal = self.ordinal
+                else:
+                    ordinal = self.ordinal + other.n
+                return Period(ordinal=ordinal, freq=self.freq)
+
+        raise ValueError("Input has different freq from Period(freq={0})".format(self.freq))
+
     def __add__(self, other):
-        if com.is_integer(other):
+        if isinstance(other, (timedelta, np.timedelta64,
+                              offsets.Tick, offsets.DateOffset)):
+            return self._add_delta(other)
+        elif com.is_integer(other):
             if self.ordinal == tslib.iNaT:
                 ordinal = self.ordinal
             else:
@@ -180,13 +210,17 @@ def __add__(self, other):
             return NotImplemented
 
     def __sub__(self, other):
-        if com.is_integer(other):
+        if isinstance(other, (timedelta, np.timedelta64,
+                              offsets.Tick, offsets.DateOffset)):
+            neg_other = -other
+            return self + neg_other
+        elif com.is_integer(other):
             if self.ordinal == tslib.iNaT:
                 ordinal = self.ordinal
             else:
                 ordinal = self.ordinal - other
             return Period(ordinal=ordinal, freq=self.freq)
-        if isinstance(other, Period):
+        elif isinstance(other, Period):
             if other.freq != self.freq:
                 raise ValueError("Cannot do arithmetic with "
                                  "non-conforming periods")
@@ -862,6 +896,22 @@ def to_timestamp(self, freq=None, how='start'):
         new_data = tslib.periodarr_to_dt64arr(new_data.values, base)
         return DatetimeIndex(new_data, freq='infer', name=self.name)
 
+    def _add_delta(self, other):
+        if isinstance(other, (timedelta, np.timedelta64, offsets.Tick)):
+            offset = frequencies.to_offset(self.freq)
+            if isinstance(offset, offsets.Tick):
+                nanos = tslib._delta_to_nanoseconds(other)
+                offset_nanos = tslib._delta_to_nanoseconds(offset)
+                if nanos % offset_nanos == 0:
+                    return self.shift(nanos // offset_nanos)
+        elif isinstance(other, offsets.DateOffset):
+            freqstr = frequencies.get_standard_freq(other)
+            base = frequencies.get_base_alias(freqstr)
+
+            if base == self.freq:
+                return self.shift(other.n)
+        raise ValueError("Input has different freq from PeriodIndex(freq={0})".format(self.freq))
+
     def shift(self, n):
         """
         Specialized shift which produces an PeriodIndex


Test patch:
diff --git a/pandas/tests/test_base.py b/pandas/tests/test_base.py
--- a/pandas/tests/test_base.py
+++ b/pandas/tests/test_base.py
@@ -915,6 +915,8 @@ def test_resolution(self):
             self.assertEqual(idx.resolution, expected)
 
     def test_add_iadd(self):
+        tm._skip_if_not_numpy17_friendly()
+
         # union
         rng1 = pd.period_range('1/1/2000', freq='D', periods=5)
         other1 = pd.period_range('1/6/2000', freq='D', periods=5)
@@ -968,11 +970,64 @@ def test_add_iadd(self):
             tm.assert_index_equal(rng, expected)
 
         # offset
-        for delta in [pd.offsets.Hour(2), timedelta(hours=2)]:
-            rng = pd.period_range('2000-01-01', '2000-02-01')
-            with tm.assertRaisesRegexp(TypeError, 'unsupported operand type\(s\)'):
+        # DateOffset
+        rng = pd.period_range('2014', '2024', freq='A')
+        result = rng + pd.offsets.YearEnd(5)
+        expected = pd.period_range('2019', '2029', freq='A')
+        tm.assert_index_equal(result, expected)
+        rng += pd.offsets.YearEnd(5)
+        tm.assert_index_equal(rng, expected)
+
+        for o in [pd.offsets.YearBegin(2), pd.offsets.MonthBegin(1), pd.offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                rng + o
+
+        rng = pd.period_range('2014-01', '2016-12', freq='M')
+        result = rng + pd.offsets.MonthEnd(5)
+        expected = pd.period_range('2014-06', '2017-05', freq='M')
+        tm.assert_index_equal(result, expected)
+        rng += pd.offsets.MonthEnd(5)
+        tm.assert_index_equal(rng, expected)
+
+        for o in [pd.offsets.YearBegin(2), pd.offsets.MonthBegin(1), pd.offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            rng = pd.period_range('2014-01', '2016-12', freq='M')
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                rng + o
+
+        # Tick
+        offsets = [pd.offsets.Day(3), timedelta(days=3), np.timedelta64(3, 'D'),
+                   pd.offsets.Hour(72), timedelta(minutes=60*24*3), np.timedelta64(72, 'h')]
+        for delta in offsets:
+            rng = pd.period_range('2014-05-01', '2014-05-15', freq='D')
+            result = rng + delta
+            expected = pd.period_range('2014-05-04', '2014-05-18', freq='D')
+            tm.assert_index_equal(result, expected)
+            rng += delta
+            tm.assert_index_equal(rng, expected)
+
+        for o in [pd.offsets.YearBegin(2), pd.offsets.MonthBegin(1), pd.offsets.Minute(),
+                  np.timedelta64(4, 'h'), timedelta(hours=23)]:
+            rng = pd.period_range('2014-05-01', '2014-05-15', freq='D')
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                rng + o
+
+        offsets = [pd.offsets.Hour(2), timedelta(hours=2), np.timedelta64(2, 'h'),
+                   pd.offsets.Minute(120), timedelta(minutes=120), np.timedelta64(120, 'm')]
+        for delta in offsets:
+            rng = pd.period_range('2014-01-01 10:00', '2014-01-05 10:00', freq='H')
+            result = rng + delta
+            expected = pd.period_range('2014-01-01 12:00', '2014-01-05 12:00', freq='H')
+            tm.assert_index_equal(result, expected)
+            rng += delta
+            tm.assert_index_equal(rng, expected)
+
+        for delta in [pd.offsets.YearBegin(2), timedelta(minutes=30), np.timedelta64(30, 's')]:
+            rng = pd.period_range('2014-01-01 10:00', '2014-01-05 10:00', freq='H')
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
                 result = rng + delta
-            with tm.assertRaisesRegexp(TypeError, 'unsupported operand type\(s\)'):
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
                 rng += delta
 
         # int
@@ -984,6 +1039,8 @@ def test_add_iadd(self):
         tm.assert_index_equal(rng, expected)
 
     def test_sub_isub(self):
+        tm._skip_if_not_numpy17_friendly()
+
         # diff
         rng1 = pd.period_range('1/1/2000', freq='D', periods=5)
         other1 = pd.period_range('1/6/2000', freq='D', periods=5)
@@ -1027,10 +1084,65 @@ def test_sub_isub(self):
             tm.assert_index_equal(rng, expected)
 
         # offset
-        for delta in [pd.offsets.Hour(2), timedelta(hours=2)]:
-            with tm.assertRaisesRegexp(TypeError, 'unsupported operand type\(s\)'):
+        # DateOffset
+        rng = pd.period_range('2014', '2024', freq='A')
+        result = rng - pd.offsets.YearEnd(5)
+        expected = pd.period_range('2009', '2019', freq='A')
+        tm.assert_index_equal(result, expected)
+        rng -= pd.offsets.YearEnd(5)
+        tm.assert_index_equal(rng, expected)
+
+        for o in [pd.offsets.YearBegin(2), pd.offsets.MonthBegin(1), pd.offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            rng = pd.period_range('2014', '2024', freq='A')
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                rng - o
+
+        rng = pd.period_range('2014-01', '2016-12', freq='M')
+        result = rng - pd.offsets.MonthEnd(5)
+        expected = pd.period_range('2013-08', '2016-07', freq='M')
+        tm.assert_index_equal(result, expected)
+        rng -= pd.offsets.MonthEnd(5)
+        tm.assert_index_equal(rng, expected)
+
+        for o in [pd.offsets.YearBegin(2), pd.offsets.MonthBegin(1), pd.offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            rng = pd.period_range('2014-01', '2016-12', freq='M')
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                rng - o
+
+        # Tick
+        offsets = [pd.offsets.Day(3), timedelta(days=3), np.timedelta64(3, 'D'),
+                   pd.offsets.Hour(72), timedelta(minutes=60*24*3), np.timedelta64(72, 'h')]
+        for delta in offsets:
+            rng = pd.period_range('2014-05-01', '2014-05-15', freq='D')
+            result = rng - delta
+            expected = pd.period_range('2014-04-28', '2014-05-12', freq='D')
+            tm.assert_index_equal(result, expected)
+            rng -= delta
+            tm.assert_index_equal(rng, expected)
+
+        for o in [pd.offsets.YearBegin(2), pd.offsets.MonthBegin(1), pd.offsets.Minute(),
+                  np.timedelta64(4, 'h'), timedelta(hours=23)]:
+            rng = pd.period_range('2014-05-01', '2014-05-15', freq='D')
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                rng - o
+
+        offsets = [pd.offsets.Hour(2), timedelta(hours=2), np.timedelta64(2, 'h'),
+                   pd.offsets.Minute(120), timedelta(minutes=120), np.timedelta64(120, 'm')]
+        for delta in offsets:
+            rng = pd.period_range('2014-01-01 10:00', '2014-01-05 10:00', freq='H')
+            result = rng - delta
+            expected = pd.period_range('2014-01-01 08:00', '2014-01-05 08:00', freq='H')
+            tm.assert_index_equal(result, expected)
+            rng -= delta
+            tm.assert_index_equal(rng, expected)
+
+        for delta in [pd.offsets.YearBegin(2), timedelta(minutes=30), np.timedelta64(30, 's')]:
+            rng = pd.period_range('2014-01-01 10:00', '2014-01-05 10:00', freq='H')
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
                 result = rng + delta
-            with tm.assertRaisesRegexp(TypeError, 'unsupported operand type\(s\)'):
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
                 rng += delta
 
         # int
diff --git a/pandas/tseries/tests/test_period.py b/pandas/tseries/tests/test_period.py
--- a/pandas/tseries/tests/test_period.py
+++ b/pandas/tseries/tests/test_period.py
@@ -16,6 +16,7 @@
 from pandas.tseries.index import DatetimeIndex, date_range, Index
 from pandas.tseries.tools import to_datetime
 import pandas.tseries.period as period
+import pandas.tseries.offsets as offsets
 
 import pandas.core.datetools as datetools
 import pandas as pd
@@ -26,7 +27,7 @@
 from pandas import Series, TimeSeries, DataFrame, _np_version_under1p9
 from pandas import tslib
 from pandas.util.testing import(assert_series_equal, assert_almost_equal,
-                                assertRaisesRegexp)
+                                assertRaisesRegexp, _skip_if_not_numpy17_friendly)
 import pandas.util.testing as tm
 from pandas import compat
 from numpy.testing import assert_array_equal
@@ -2484,6 +2485,190 @@ def test_add(self):
         with tm.assertRaisesRegexp(TypeError, msg):
             dt1 + dt2
 
+    def test_add_offset(self):
+        _skip_if_not_numpy17_friendly()
+
+        # freq is DateOffset
+        p = Period('2011', freq='A')
+        self.assertEqual(p + offsets.YearEnd(2), Period('2013', freq='A'))
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                p + o
+
+        p = Period('2011-03', freq='M')
+        self.assertEqual(p + offsets.MonthEnd(2), Period('2011-05', freq='M'))
+        self.assertEqual(p + offsets.MonthEnd(12), Period('2012-03', freq='M'))
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                p + o
+
+        # freq is Tick
+        p = Period('2011-04-01', freq='D')
+        self.assertEqual(p + offsets.Day(5), Period('2011-04-06', freq='D'))
+        self.assertEqual(p + offsets.Hour(24), Period('2011-04-02', freq='D'))
+        self.assertEqual(p + np.timedelta64(2, 'D'), Period('2011-04-03', freq='D'))
+        self.assertEqual(p + np.timedelta64(3600 * 24, 's'), Period('2011-04-02', freq='D'))
+        self.assertEqual(p + timedelta(-2), Period('2011-03-30', freq='D'))
+        self.assertEqual(p + timedelta(hours=48), Period('2011-04-03', freq='D'))
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(4, 'h'), timedelta(hours=23)]:
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                p + o
+
+        p = Period('2011-04-01 09:00', freq='H')
+        self.assertEqual(p + offsets.Day(2), Period('2011-04-03 09:00', freq='H'))
+        self.assertEqual(p + offsets.Hour(3), Period('2011-04-01 12:00', freq='H'))
+        self.assertEqual(p + np.timedelta64(3, 'h'), Period('2011-04-01 12:00', freq='H'))
+        self.assertEqual(p + np.timedelta64(3600, 's'), Period('2011-04-01 10:00', freq='H'))
+        self.assertEqual(p + timedelta(minutes=120), Period('2011-04-01 11:00', freq='H'))
+        self.assertEqual(p + timedelta(days=4, minutes=180), Period('2011-04-05 12:00', freq='H'))
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(3200, 's'), timedelta(hours=23, minutes=30)]:
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                p + o
+
+    def test_add_offset_nat(self):
+        _skip_if_not_numpy17_friendly()
+
+        # freq is DateOffset
+        p = Period('NaT', freq='A')
+        for o in [offsets.YearEnd(2)]:
+            self.assertEqual((p + o).ordinal, tslib.iNaT)
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            with tm.assertRaises(ValueError):
+                p + o
+
+        p = Period('NaT', freq='M')
+        for o in [offsets.MonthEnd(2), offsets.MonthEnd(12)]:
+            self.assertEqual((p + o).ordinal, tslib.iNaT)
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                p + o
+
+        # freq is Tick
+        p = Period('NaT', freq='D')
+        for o in [offsets.Day(5), offsets.Hour(24), np.timedelta64(2, 'D'),
+                  np.timedelta64(3600 * 24, 's'), timedelta(-2), timedelta(hours=48)]:
+            self.assertEqual((p + o).ordinal, tslib.iNaT)
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(4, 'h'), timedelta(hours=23)]:
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                p + o
+
+        p = Period('NaT', freq='H')
+        for o in [offsets.Day(2), offsets.Hour(3), np.timedelta64(3, 'h'),
+                  np.timedelta64(3600, 's'), timedelta(minutes=120),
+                  timedelta(days=4, minutes=180)]:
+            self.assertEqual((p + o).ordinal, tslib.iNaT)
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(3200, 's'), timedelta(hours=23, minutes=30)]:
+            with tm.assertRaisesRegexp(ValueError, 'Input has different freq from Period'):
+                p + o
+
+    def test_sub_offset(self):
+        _skip_if_not_numpy17_friendly()
+
+        # freq is DateOffset
+        p = Period('2011', freq='A')
+        self.assertEqual(p - offsets.YearEnd(2), Period('2009', freq='A'))
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            with tm.assertRaises(ValueError):
+                p - o
+
+        p = Period('2011-03', freq='M')
+        self.assertEqual(p - offsets.MonthEnd(2), Period('2011-01', freq='M'))
+        self.assertEqual(p - offsets.MonthEnd(12), Period('2010-03', freq='M'))
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            with tm.assertRaises(ValueError):
+                p - o
+
+        # freq is Tick
+        p = Period('2011-04-01', freq='D')
+        self.assertEqual(p - offsets.Day(5), Period('2011-03-27', freq='D'))
+        self.assertEqual(p - offsets.Hour(24), Period('2011-03-31', freq='D'))
+        self.assertEqual(p - np.timedelta64(2, 'D'), Period('2011-03-30', freq='D'))
+        self.assertEqual(p - np.timedelta64(3600 * 24, 's'), Period('2011-03-31', freq='D'))
+        self.assertEqual(p - timedelta(-2), Period('2011-04-03', freq='D'))
+        self.assertEqual(p - timedelta(hours=48), Period('2011-03-30', freq='D'))
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(4, 'h'), timedelta(hours=23)]:
+            with tm.assertRaises(ValueError):
+                p - o
+
+        p = Period('2011-04-01 09:00', freq='H')
+        self.assertEqual(p - offsets.Day(2), Period('2011-03-30 09:00', freq='H'))
+        self.assertEqual(p - offsets.Hour(3), Period('2011-04-01 06:00', freq='H'))
+        self.assertEqual(p - np.timedelta64(3, 'h'), Period('2011-04-01 06:00', freq='H'))
+        self.assertEqual(p - np.timedelta64(3600, 's'), Period('2011-04-01 08:00', freq='H'))
+        self.assertEqual(p - timedelta(minutes=120), Period('2011-04-01 07:00', freq='H'))
+        self.assertEqual(p - timedelta(days=4, minutes=180), Period('2011-03-28 06:00', freq='H'))
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(3200, 's'), timedelta(hours=23, minutes=30)]:
+            with tm.assertRaises(ValueError):
+                p - o
+
+    def test_sub_offset_nat(self):
+        _skip_if_not_numpy17_friendly()
+
+        # freq is DateOffset
+        p = Period('NaT', freq='A')
+        for o in [offsets.YearEnd(2)]:
+            self.assertEqual((p - o).ordinal, tslib.iNaT)
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            with tm.assertRaises(ValueError):
+                p - o
+
+        p = Period('NaT', freq='M')
+        for o in [offsets.MonthEnd(2), offsets.MonthEnd(12)]:
+            self.assertEqual((p - o).ordinal, tslib.iNaT)
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(365, 'D'), timedelta(365)]:
+            with tm.assertRaises(ValueError):
+                p - o
+
+        # freq is Tick
+        p = Period('NaT', freq='D')
+        for o in [offsets.Day(5), offsets.Hour(24), np.timedelta64(2, 'D'),
+                  np.timedelta64(3600 * 24, 's'), timedelta(-2), timedelta(hours=48)]:
+            self.assertEqual((p - o).ordinal, tslib.iNaT)
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(4, 'h'), timedelta(hours=23)]:
+            with tm.assertRaises(ValueError):
+                p - o
+
+        p = Period('NaT', freq='H')
+        for o in [offsets.Day(2), offsets.Hour(3), np.timedelta64(3, 'h'),
+                  np.timedelta64(3600, 's'), timedelta(minutes=120),
+                  timedelta(days=4, minutes=180)]:
+            self.assertEqual((p - o).ordinal, tslib.iNaT)
+
+        for o in [offsets.YearBegin(2), offsets.MonthBegin(1), offsets.Minute(),
+                  np.timedelta64(3200, 's'), timedelta(hours=23, minutes=30)]:
+            with tm.assertRaises(ValueError):
+                p - o
+
     def test_nat_ops(self):
         p = Period('NaT', freq='M')
         self.assertEqual((p + 1).ordinal, tslib.iNaT)