1
1
# -*- coding: utf-8 -*-
2
+ from datetime import timedelta
3
+ import warnings
2
4
5
+ import numpy as np
6
+
7
+ from pandas ._libs import lib
3
8
from pandas ._libs .tslib import NaT
4
- from pandas ._libs .tslibs .period import Period
9
+ from pandas ._libs .tslibs .period import (
10
+ Period , IncompatibleFrequency , DIFFERENT_FREQ_INDEX )
11
+ from pandas ._libs .tslibs .timedeltas import delta_to_nanoseconds
5
12
6
13
from pandas .util ._decorators import cache_readonly
7
14
8
15
from pandas .core .dtypes .dtypes import PeriodDtype
9
16
17
+ from pandas .tseries import frequencies
18
+ from pandas .tseries .offsets import Tick , DateOffset
19
+
10
20
from .datetimelike import DatetimeLikeArrayMixin
11
21
12
22
@@ -28,9 +38,70 @@ def _ndarray_values(self):
28
38
def asi8 (self ):
29
39
return self ._ndarray_values .view ('i8' )
30
40
41
+ @property
42
+ def freq (self ):
43
+ """Return the frequency object if it is set, otherwise None"""
44
+ return self ._freq
45
+
46
+ @freq .setter
47
+ def freq (self , value ):
48
+ msg = ('Setting {cls}.freq has been deprecated and will be '
49
+ 'removed in a future version; use PeriodIndex.asfreq instead. '
50
+ 'The {cls}.freq setter is not guaranteed to work.' )
51
+ warnings .warn (msg .format (cls = type (self ).__name__ ),
52
+ FutureWarning , stacklevel = 2 )
53
+ self ._freq = value
54
+
31
55
# ------------------------------------------------------------------
32
56
# Arithmetic Methods
33
57
34
58
def _sub_datelike (self , other ):
35
59
assert other is not NaT
36
60
return NotImplemented
61
+
62
+ def _maybe_convert_timedelta (self , other ):
63
+ """
64
+ Convert timedelta-like input to an integer multiple of self.freq
65
+
66
+ Parameters
67
+ ----------
68
+ other : timedelta, np.timedelta64, DateOffset, int, np.ndarray
69
+
70
+ Returns
71
+ -------
72
+ converted : int, np.ndarray[int64]
73
+
74
+ Raises
75
+ ------
76
+ IncompatibleFrequency : if the input cannot be written as a multiple
77
+ of self.freq. Note IncompatibleFrequency subclasses ValueError.
78
+ """
79
+ if isinstance (
80
+ other , (timedelta , np .timedelta64 , Tick , np .ndarray )):
81
+ offset = frequencies .to_offset (self .freq .rule_code )
82
+ if isinstance (offset , Tick ):
83
+ if isinstance (other , np .ndarray ):
84
+ nanos = np .vectorize (delta_to_nanoseconds )(other )
85
+ else :
86
+ nanos = delta_to_nanoseconds (other )
87
+ offset_nanos = delta_to_nanoseconds (offset )
88
+ check = np .all (nanos % offset_nanos == 0 )
89
+ if check :
90
+ return nanos // offset_nanos
91
+ elif isinstance (other , DateOffset ):
92
+ freqstr = other .rule_code
93
+ base = frequencies .get_base_alias (freqstr )
94
+ if base == self .freq .rule_code :
95
+ return other .n
96
+ msg = DIFFERENT_FREQ_INDEX .format (self .freqstr , other .freqstr )
97
+ raise IncompatibleFrequency (msg )
98
+ elif lib .is_integer (other ):
99
+ # integer is passed to .shift via
100
+ # _add_datetimelike_methods basically
101
+ # but ufunc may pass integer to _add_delta
102
+ return other
103
+
104
+ # raise when input doesn't have freq
105
+ msg = "Input has different freq from {cls}(freq={freqstr})"
106
+ raise IncompatibleFrequency (msg .format (cls = type (self ).__name__ ,
107
+ freqstr = self .freqstr ))
0 commit comments