1818from pandas ._libs .tslibs .offsets import (
1919 ApplyTypeError ,
2020 as_datetime , _is_normalized ,
21- _get_firstbday , _get_calendar , _to_dt64 , _validate_business_time ,
21+ get_firstbday , get_lastbday ,
22+ _get_calendar , _to_dt64 , _validate_business_time ,
2223 _int_to_weekday , _weekday_to_int ,
2324 _determine_offset ,
2425 apply_index_wraps ,
@@ -1181,18 +1182,14 @@ class BusinessMonthEnd(MonthOffset):
11811182 def apply (self , other ):
11821183 n = self .n
11831184 wkday , days_in_month = tslib .monthrange (other .year , other .month )
1184- lastBDay = days_in_month - max (((wkday + days_in_month - 1 )
1185- % 7 ) - 4 , 0 )
1185+ lastBDay = get_lastbday (wkday , days_in_month )
11861186
11871187 if n > 0 and not other .day >= lastBDay :
11881188 n = n - 1
11891189 elif n <= 0 and other .day > lastBDay :
11901190 n = n + 1
1191- other = shift_month (other , n , 'end' )
11921191
1193- if other .weekday () > 4 :
1194- other = other - BDay ()
1195- return other
1192+ return shift_month (other , n , 'business_end' )
11961193
11971194
11981195class BusinessMonthBegin (MonthOffset ):
@@ -1203,7 +1200,7 @@ class BusinessMonthBegin(MonthOffset):
12031200 def apply (self , other ):
12041201 n = self .n
12051202 wkday , _ = tslib .monthrange (other .year , other .month )
1206- first = _get_firstbday (wkday )
1203+ first = get_firstbday (wkday )
12071204
12081205 if other .day > first and n <= 0 :
12091206 # as if rolled forward already
@@ -1212,24 +1209,13 @@ def apply(self, other):
12121209 other = other + timedelta (days = first - other .day )
12131210 n -= 1
12141211
1215- other = shift_month (other , n , None )
1216- wkday , _ = tslib .monthrange (other .year , other .month )
1217- first = _get_firstbday (wkday )
1218- result = datetime (other .year , other .month , first ,
1219- other .hour , other .minute ,
1220- other .second , other .microsecond )
1221- return result
1212+ return shift_month (other , n , 'business_start' )
12221213
12231214 def onOffset (self , dt ):
12241215 if self .normalize and not _is_normalized (dt ):
12251216 return False
12261217 first_weekday , _ = tslib .monthrange (dt .year , dt .month )
1227- if first_weekday == 5 :
1228- return dt .day == 3
1229- elif first_weekday == 6 :
1230- return dt .day == 2
1231- else :
1232- return dt .day == 1
1218+ return dt .day == get_firstbday (first_weekday )
12331219
12341220
12351221class CustomBusinessMonthEnd (BusinessMixin , MonthOffset ):
@@ -1611,10 +1597,7 @@ def _from_name(cls, suffix=None):
16111597
16121598class QuarterOffset (DateOffset ):
16131599 """Quarter representation - doesn't call super"""
1614-
1615- #: default month for __init__
16161600 _default_startingMonth = None
1617- #: default month in _from_name
16181601 _from_name_startingMonth = None
16191602 _adjust_dst = True
16201603 # TODO: Consider combining QuarterOffset and YearOffset __init__ at some
@@ -1656,21 +1639,15 @@ class BQuarterEnd(QuarterOffset):
16561639 """
16571640 _outputName = 'BusinessQuarterEnd'
16581641 _default_startingMonth = 3
1659- # 'BQ'
16601642 _from_name_startingMonth = 12
16611643 _prefix = 'BQ'
16621644
16631645 @apply_wraps
16641646 def apply (self , other ):
16651647 n = self .n
1666- base = other
1667- other = datetime (other .year , other .month , other .day ,
1668- other .hour , other .minute , other .second ,
1669- other .microsecond )
16701648
16711649 wkday , days_in_month = tslib .monthrange (other .year , other .month )
1672- lastBDay = days_in_month - max (((wkday + days_in_month - 1 )
1673- % 7 ) - 4 , 0 )
1650+ lastBDay = get_lastbday (wkday , days_in_month )
16741651
16751652 monthsToGo = 3 - ((other .month - self .startingMonth ) % 3 )
16761653 if monthsToGo == 3 :
@@ -1681,11 +1658,7 @@ def apply(self, other):
16811658 elif n <= 0 and other .day > lastBDay and monthsToGo == 0 :
16821659 n = n + 1
16831660
1684- other = shift_month (other , monthsToGo + 3 * n , 'end' )
1685- other = tslib ._localize_pydatetime (other , base .tzinfo )
1686- if other .weekday () > 4 :
1687- other = other - BDay ()
1688- return other
1661+ return shift_month (other , monthsToGo + 3 * n , 'business_end' )
16891662
16901663 def onOffset (self , dt ):
16911664 if self .normalize and not _is_normalized (dt ):
@@ -1711,7 +1684,7 @@ def apply(self, other):
17111684 n = self .n
17121685 wkday , _ = tslib .monthrange (other .year , other .month )
17131686
1714- first = _get_firstbday (wkday )
1687+ first = get_firstbday (wkday )
17151688
17161689 monthsSince = (other .month - self .startingMonth ) % 3
17171690
@@ -1725,14 +1698,7 @@ def apply(self, other):
17251698 elif n > 0 and (monthsSince == 0 and other .day < first ):
17261699 n = n - 1
17271700
1728- # get the first bday for result
1729- other = shift_month (other , 3 * n - monthsSince , None )
1730- wkday , _ = tslib .monthrange (other .year , other .month )
1731- first = _get_firstbday (wkday )
1732- result = datetime (other .year , other .month , first ,
1733- other .hour , other .minute , other .second ,
1734- other .microsecond )
1735- return result
1701+ return shift_month (other , 3 * n - monthsSince , 'business_start' )
17361702
17371703
17381704class QuarterEnd (EndMixin , QuarterOffset ):
@@ -1841,8 +1807,7 @@ class BYearEnd(YearOffset):
18411807 def apply (self , other ):
18421808 n = self .n
18431809 wkday , days_in_month = tslib .monthrange (other .year , self .month )
1844- lastBDay = (days_in_month -
1845- max (((wkday + days_in_month - 1 ) % 7 ) - 4 , 0 ))
1810+ lastBDay = get_lastbday (wkday , days_in_month )
18461811
18471812 years = n
18481813 if n > 0 :
@@ -1854,17 +1819,8 @@ def apply(self, other):
18541819 (other .month == self .month and other .day > lastBDay )):
18551820 years += 1
18561821
1857- other = shift_month (other , 12 * years , None )
1858-
1859- _ , days_in_month = tslib .monthrange (other .year , self .month )
1860- result = datetime (other .year , self .month , days_in_month ,
1861- other .hour , other .minute , other .second ,
1862- other .microsecond )
1863-
1864- if result .weekday () > 4 :
1865- result = result - BDay ()
1866-
1867- return result
1822+ months = years * 12 + (self .month - other .month )
1823+ return shift_month (other , months , 'business_end' )
18681824
18691825
18701826class BYearBegin (YearOffset ):
@@ -1878,7 +1834,7 @@ def apply(self, other):
18781834 n = self .n
18791835 wkday , days_in_month = tslib .monthrange (other .year , self .month )
18801836
1881- first = _get_firstbday (wkday )
1837+ first = get_firstbday (wkday )
18821838
18831839 years = n
18841840
@@ -1892,11 +1848,8 @@ def apply(self, other):
18921848 years += 1
18931849
18941850 # set first bday for result
1895- other = shift_month (other , years * 12 , None )
1896- wkday , days_in_month = tslib .monthrange (other .year , self .month )
1897- first = _get_firstbday (wkday )
1898- return datetime (other .year , self .month , first , other .hour ,
1899- other .minute , other .second , other .microsecond )
1851+ months = years * 12 + (self .month - other .month )
1852+ return shift_month (other , months , 'business_start' )
19001853
19011854
19021855class YearEnd (EndMixin , YearOffset ):
0 commit comments