22
22
_int_to_weekday , _weekday_to_int ,
23
23
_determine_offset ,
24
24
apply_index_wraps ,
25
+ shift_month ,
25
26
BeginMixin , EndMixin ,
26
27
BaseOffset )
27
28
@@ -252,6 +253,8 @@ def apply_index(self, i):
252
253
"applied vectorized" .format (kwd = kwd ))
253
254
254
255
def isAnchored (self ):
256
+ # TODO: Does this make sense for the general case? It would help
257
+ # if there were a canonical docstring for what isAnchored means.
255
258
return (self .n == 1 )
256
259
257
260
def _params (self ):
@@ -721,6 +724,7 @@ def apply(self, other):
721
724
722
725
return result
723
726
else :
727
+ # TODO: Figure out the end of this sente
724
728
raise ApplyTypeError (
725
729
'Only know how to combine business hour with ' )
726
730
@@ -927,10 +931,10 @@ def apply(self, other):
927
931
n = self .n
928
932
_ , days_in_month = tslib .monthrange (other .year , other .month )
929
933
if other .day != days_in_month :
930
- other = other + relativedelta ( months = - 1 , day = 31 )
934
+ other = shift_month ( other , - 1 , 'end' )
931
935
if n <= 0 :
932
936
n = n + 1
933
- other = other + relativedelta ( months = n , day = 31 )
937
+ other = shift_month ( other , n , 'end' )
934
938
return other
935
939
936
940
@apply_index_wraps
@@ -956,7 +960,7 @@ def apply(self, other):
956
960
if other .day > 1 and n <= 0 : # then roll forward if n<=0
957
961
n += 1
958
962
959
- return other + relativedelta ( months = n , day = 1 )
963
+ return shift_month ( other , n , 'start' )
960
964
961
965
@apply_index_wraps
962
966
def apply_index (self , i ):
@@ -1002,12 +1006,12 @@ def apply(self, other):
1002
1006
if not self .onOffset (other ):
1003
1007
_ , days_in_month = tslib .monthrange (other .year , other .month )
1004
1008
if 1 < other .day < self .day_of_month :
1005
- other += relativedelta (day = self .day_of_month )
1009
+ other = other . replace (day = self .day_of_month )
1006
1010
if n > 0 :
1007
1011
# rollforward so subtract 1
1008
1012
n -= 1
1009
1013
elif self .day_of_month < other .day < days_in_month :
1010
- other += relativedelta (day = self .day_of_month )
1014
+ other = other . replace (day = self .day_of_month )
1011
1015
if n < 0 :
1012
1016
# rollforward in the negative direction so add 1
1013
1017
n += 1
@@ -1084,19 +1088,19 @@ def onOffset(self, dt):
1084
1088
def _apply (self , n , other ):
1085
1089
# if other.day is not day_of_month move to day_of_month and update n
1086
1090
if other .day < self .day_of_month :
1087
- other += relativedelta (day = self .day_of_month )
1091
+ other = other . replace (day = self .day_of_month )
1088
1092
if n > 0 :
1089
1093
n -= 1
1090
1094
elif other .day > self .day_of_month :
1091
- other += relativedelta (day = self .day_of_month )
1095
+ other = other . replace (day = self .day_of_month )
1092
1096
if n == 0 :
1093
1097
n = 1
1094
1098
else :
1095
1099
n += 1
1096
1100
1097
1101
months = n // 2
1098
1102
day = 31 if n % 2 else self .day_of_month
1099
- return other + relativedelta ( months = months , day = day )
1103
+ return shift_month ( other , months , day )
1100
1104
1101
1105
def _get_roll (self , i , before_day_of_month , after_day_of_month ):
1102
1106
n = self .n
@@ -1141,21 +1145,21 @@ def onOffset(self, dt):
1141
1145
def _apply (self , n , other ):
1142
1146
# if other.day is not day_of_month move to day_of_month and update n
1143
1147
if other .day < self .day_of_month :
1144
- other += relativedelta (day = self .day_of_month )
1148
+ other = other . replace (day = self .day_of_month )
1145
1149
if n == 0 :
1146
1150
n = - 1
1147
1151
else :
1148
1152
n -= 1
1149
1153
elif other .day > self .day_of_month :
1150
- other += relativedelta (day = self .day_of_month )
1154
+ other = other . replace (day = self .day_of_month )
1151
1155
if n == 0 :
1152
1156
n = 1
1153
1157
elif n < 0 :
1154
1158
n += 1
1155
1159
1156
1160
months = n // 2 + n % 2
1157
1161
day = 1 if n % 2 else self .day_of_month
1158
- return other + relativedelta ( months = months , day = day )
1162
+ return shift_month ( other , months , day )
1159
1163
1160
1164
def _get_roll (self , i , before_day_of_month , after_day_of_month ):
1161
1165
n = self .n
@@ -1191,7 +1195,7 @@ def apply(self, other):
1191
1195
n = n - 1
1192
1196
elif n <= 0 and other .day > lastBDay :
1193
1197
n = n + 1
1194
- other = other + relativedelta ( months = n , day = 31 )
1198
+ other = shift_month ( other , n , 'end' )
1195
1199
1196
1200
if other .weekday () > 4 :
1197
1201
other = other - BDay ()
@@ -1215,7 +1219,7 @@ def apply(self, other):
1215
1219
other = other + timedelta (days = first - other .day )
1216
1220
n -= 1
1217
1221
1218
- other = other + relativedelta ( months = n )
1222
+ other = shift_month ( other , n , None )
1219
1223
wkday , _ = tslib .monthrange (other .year , other .month )
1220
1224
first = _get_firstbday (wkday )
1221
1225
result = datetime (other .year , other .month , first ,
@@ -1520,8 +1524,7 @@ def apply(self, other):
1520
1524
else :
1521
1525
months = self .n + 1
1522
1526
1523
- other = self .getOffsetOfMonth (
1524
- other + relativedelta (months = months , day = 1 ))
1527
+ other = self .getOffsetOfMonth (shift_month (other , months , 'start' ))
1525
1528
other = datetime (other .year , other .month , other .day , base .hour ,
1526
1529
base .minute , base .second , base .microsecond )
1527
1530
return other
@@ -1612,8 +1615,7 @@ def apply(self, other):
1612
1615
else :
1613
1616
months = self .n + 1
1614
1617
1615
- return self .getOffsetOfMonth (
1616
- other + relativedelta (months = months , day = 1 ))
1618
+ return self .getOffsetOfMonth (shift_month (other , months , 'start' ))
1617
1619
1618
1620
def getOffsetOfMonth (self , dt ):
1619
1621
m = MonthEnd ()
@@ -1716,7 +1718,7 @@ def apply(self, other):
1716
1718
elif n <= 0 and other .day > lastBDay and monthsToGo == 0 :
1717
1719
n = n + 1
1718
1720
1719
- other = other + relativedelta ( months = monthsToGo + 3 * n , day = 31 )
1721
+ other = shift_month ( other , monthsToGo + 3 * n , 'end' )
1720
1722
other = tslib ._localize_pydatetime (other , base .tzinfo )
1721
1723
if other .weekday () > 4 :
1722
1724
other = other - BDay ()
@@ -1761,7 +1763,7 @@ def apply(self, other):
1761
1763
n = n - 1
1762
1764
1763
1765
# get the first bday for result
1764
- other = other + relativedelta ( months = 3 * n - monthsSince )
1766
+ other = shift_month ( other , 3 * n - monthsSince , None )
1765
1767
wkday , _ = tslib .monthrange (other .year , other .month )
1766
1768
first = _get_firstbday (wkday )
1767
1769
result = datetime (other .year , other .month , first ,
@@ -1795,7 +1797,7 @@ def apply(self, other):
1795
1797
if n > 0 and not (other .day >= days_in_month and monthsToGo == 0 ):
1796
1798
n = n - 1
1797
1799
1798
- other = other + relativedelta ( months = monthsToGo + 3 * n , day = 31 )
1800
+ other = shift_month ( other , monthsToGo + 3 * n , 'end' )
1799
1801
return other
1800
1802
1801
1803
@apply_index_wraps
@@ -1830,7 +1832,7 @@ def apply(self, other):
1830
1832
# after start, so come back an extra period as if rolled forward
1831
1833
n = n + 1
1832
1834
1833
- other = other + relativedelta ( months = 3 * n - monthsSince , day = 1 )
1835
+ other = shift_month ( other , 3 * n - monthsSince , 'start' )
1834
1836
return other
1835
1837
1836
1838
@apply_index_wraps
@@ -1889,7 +1891,7 @@ def apply(self, other):
1889
1891
(other .month == self .month and other .day > lastBDay )):
1890
1892
years += 1
1891
1893
1892
- other = other + relativedelta ( years = years )
1894
+ other = shift_month ( other , 12 * years , None )
1893
1895
1894
1896
_ , days_in_month = tslib .monthrange (other .year , self .month )
1895
1897
result = datetime (other .year , self .month , days_in_month ,
@@ -1927,7 +1929,7 @@ def apply(self, other):
1927
1929
years += 1
1928
1930
1929
1931
# set first bday for result
1930
- other = other + relativedelta ( years = years )
1932
+ other = shift_month ( other , years * 12 , None )
1931
1933
wkday , days_in_month = tslib .monthrange (other .year , self .month )
1932
1934
first = _get_firstbday (wkday )
1933
1935
return datetime (other .year , self .month , first , other .hour ,
@@ -2145,8 +2147,8 @@ def onOffset(self, dt):
2145
2147
2146
2148
if self .variation == "nearest" :
2147
2149
# We have to check the year end of "this" cal year AND the previous
2148
- return year_end == dt or \
2149
- self .get_year_end (dt - relativedelta ( months = 1 )) == dt
2150
+ return ( year_end == dt or
2151
+ self .get_year_end (shift_month ( dt , - 1 , None )) == dt )
2150
2152
else :
2151
2153
return year_end == dt
2152
2154
@@ -2226,8 +2228,8 @@ def get_year_end(self, dt):
2226
2228
def get_target_month_end (self , dt ):
2227
2229
target_month = datetime (
2228
2230
dt .year , self .startingMonth , 1 , tzinfo = dt .tzinfo )
2229
- next_month_first_of = target_month + relativedelta ( months = + 1 )
2230
- return next_month_first_of + relativedelta (days = - 1 )
2231
+ next_month_first_of = shift_month ( target_month , 1 , None )
2232
+ return next_month_first_of + timedelta (days = - 1 )
2231
2233
2232
2234
def _get_year_end_nearest (self , dt ):
2233
2235
target_date = self .get_target_month_end (dt )
@@ -2382,7 +2384,7 @@ def apply(self, other):
2382
2384
qtr_lens = self .get_weeks (other + self ._offset )
2383
2385
2384
2386
for weeks in qtr_lens :
2385
- start += relativedelta (weeks = weeks )
2387
+ start += timedelta (weeks = weeks )
2386
2388
if start > other :
2387
2389
other = start
2388
2390
n -= 1
@@ -2399,7 +2401,7 @@ def apply(self, other):
2399
2401
qtr_lens = self .get_weeks (other )
2400
2402
2401
2403
for weeks in reversed (qtr_lens ):
2402
- end -= relativedelta (weeks = weeks )
2404
+ end -= timedelta (weeks = weeks )
2403
2405
if end < other :
2404
2406
other = end
2405
2407
n -= 1
@@ -2442,7 +2444,7 @@ def onOffset(self, dt):
2442
2444
2443
2445
current = next_year_end
2444
2446
for qtr_len in qtr_lens [0 :4 ]:
2445
- current += relativedelta (weeks = qtr_len )
2447
+ current += timedelta (weeks = qtr_len )
2446
2448
if dt == current :
2447
2449
return True
2448
2450
return False
0 commit comments