Implement business_start/end cases for shift_months (#18489) · pandas-dev/pandas@f745e52 (original) (raw)

`@@ -929,8 +929,9 @@ def name(self):

`

929

929

`if self.isAnchored:

`

930

930

`return self.rule_code

`

931

931

`else:

`

``

932

`+

month = liboffsets._int_to_month[self.n]

`

932

933

`return "{code}-{month}".format(code=self.rule_code,

`

933

``

`-

month=_int_to_month[self.n])

`

``

934

`+

month=month)

`

934

935

``

935

936

`def onOffset(self, dt):

`

936

937

`if self.normalize and not _is_normalized(dt):

`

`@@ -950,28 +951,23 @@ def apply(self, other):

`

950

951

``

951

952

`return shift_month(other, n, self._day_opt)

`

952

953

``

``

954

`+

@apply_index_wraps

`

``

955

`+

def apply_index(self, i):

`

``

956

`+

shifted = liboffsets.shift_months(i.asi8, self.n, self._day_opt)

`

``

957

`+

return i._shallow_copy(shifted)

`

``

958

+

953

959

``

954

960

`class MonthEnd(MonthOffset):

`

955

961

`"""DateOffset of one month end"""

`

956

962

`_prefix = 'M'

`

957

963

`_day_opt = 'end'

`

958

964

``

959

``

`-

@apply_index_wraps

`

960

``

`-

def apply_index(self, i):

`

961

``

`-

shifted = liboffsets.shift_months(i.asi8, self.n, self._day_opt)

`

962

``

`-

return i._shallow_copy(shifted)

`

963

``

-

964

965

``

965

966

`class MonthBegin(MonthOffset):

`

966

967

`"""DateOffset of one month at beginning"""

`

967

968

`_prefix = 'MS'

`

968

969

`_day_opt = 'start'

`

969

970

``

970

``

`-

@apply_index_wraps

`

971

``

`-

def apply_index(self, i):

`

972

``

`-

shifted = liboffsets.shift_months(i.asi8, self.n, self._day_opt)

`

973

``

`-

return i._shallow_copy(shifted)

`

974

``

-

975

971

``

976

972

`class BusinessMonthEnd(MonthOffset):

`

977

973

`"""DateOffset increments between business EOM dates"""

`

`@@ -1008,6 +1004,7 @@ class CustomBusinessMonthEnd(BusinessMixin, MonthOffset):

`

1008

1004

`_prefix = 'CBM'

`

1009

1005

``

1010

1006

`onOffset = DateOffset.onOffset # override MonthOffset method

`

``

1007

`+

apply_index = DateOffset.apply_index # override MonthOffset method

`

1011

1008

``

1012

1009

`def init(self, n=1, normalize=False, weekmask='Mon Tue Wed Thu Fri',

`

1013

1010

`holidays=None, calendar=None, offset=timedelta(0)):

`

`@@ -1083,6 +1080,7 @@ class CustomBusinessMonthBegin(BusinessMixin, MonthOffset):

`

1083

1080

`_prefix = 'CBMS'

`

1084

1081

``

1085

1082

`onOffset = DateOffset.onOffset # override MonthOffset method

`

``

1083

`+

apply_index = DateOffset.apply_index # override MonthOffset method

`

1086

1084

``

1087

1085

`def init(self, n=1, normalize=False, weekmask='Mon Tue Wed Thu Fri',

`

1088

1086

`holidays=None, calendar=None, offset=timedelta(0)):

`

`@@ -1603,15 +1601,15 @@ def isAnchored(self):

`

1603

1601

`def _from_name(cls, suffix=None):

`

1604

1602

`kwargs = {}

`

1605

1603

`if suffix:

`

1606

``

`-

kwargs['startingMonth'] = _month_to_int[suffix]

`

``

1604

`+

kwargs['startingMonth'] = liboffsets._month_to_int[suffix]

`

1607

1605

`else:

`

1608

1606

`if cls._from_name_startingMonth is not None:

`

1609

1607

`kwargs['startingMonth'] = cls._from_name_startingMonth

`

1610

1608

`return cls(**kwargs)

`

1611

1609

``

1612

1610

`@property

`

1613

1611

`def rule_code(self):

`

1614

``

`-

month = _int_to_month[self.startingMonth]

`

``

1612

`+

month = liboffsets._int_to_month[self.startingMonth]

`

1615

1613

`return '{prefix}-{month}'.format(prefix=self._prefix, month=month)

`

1616

1614

``

1617

1615

`@apply_wraps

`

`@@ -1631,6 +1629,12 @@ def apply(self, other):

`

1631

1629

``

1632

1630

`return shift_month(other, 3 * n - months_since, self._day_opt)

`

1633

1631

``

``

1632

`+

def onOffset(self, dt):

`

``

1633

`+

if self.normalize and not _is_normalized(dt):

`

``

1634

`+

return False

`

``

1635

`+

modMonth = (dt.month - self.startingMonth) % 3

`

``

1636

`+

return modMonth == 0 and dt.day == self._get_offset_day(dt)

`

``

1637

+

1634

1638

``

1635

1639

`class BQuarterEnd(QuarterOffset):

`

1636

1640

`"""DateOffset increments between business Quarter dates

`

`@@ -1644,16 +1648,6 @@ class BQuarterEnd(QuarterOffset):

`

1644

1648

`_prefix = 'BQ'

`

1645

1649

`_day_opt = 'business_end'

`

1646

1650

``

1647

``

`-

def onOffset(self, dt):

`

1648

``

`-

if self.normalize and not _is_normalized(dt):

`

1649

``

`-

return False

`

1650

``

`-

modMonth = (dt.month - self.startingMonth) % 3

`

1651

``

`-

return modMonth == 0 and dt.day == self._get_offset_day(dt)

`

1652

``

-

1653

``

-

1654

``

`-

_int_to_month = tslib._MONTH_ALIASES

`

1655

``

`-

_month_to_int = {v: k for k, v in _int_to_month.items()}

`

1656

``

-

1657

1651

``

1658

1652

`# TODO: This is basically the same as BQuarterEnd

`

1659

1653

`class BQuarterBegin(QuarterOffset):

`

`@@ -1680,12 +1674,6 @@ class QuarterEnd(EndMixin, QuarterOffset):

`

1680

1674

`def apply_index(self, i):

`

1681

1675

`return self._end_apply_index(i, self.freqstr)

`

1682

1676

``

1683

``

`-

def onOffset(self, dt):

`

1684

``

`-

if self.normalize and not _is_normalized(dt):

`

1685

``

`-

return False

`

1686

``

`-

modMonth = (dt.month - self.startingMonth) % 3

`

1687

``

`-

return modMonth == 0 and dt.day == self._get_offset_day(dt)

`

1688

``

-

1689

1677

``

1690

1678

`class QuarterBegin(BeginMixin, QuarterOffset):

`

1691

1679

`_outputName = 'QuarterBegin'

`

`@@ -1697,7 +1685,8 @@ class QuarterBegin(BeginMixin, QuarterOffset):

`

1697

1685

`@apply_index_wraps

`

1698

1686

`def apply_index(self, i):

`

1699

1687

`freq_month = 12 if self.startingMonth == 1 else self.startingMonth - 1

`

1700

``

`-

freqstr = 'Q-{month}'.format(month=_int_to_month[freq_month])

`

``

1688

`+

month = liboffsets._int_to_month[freq_month]

`

``

1689

`+

freqstr = 'Q-{month}'.format(month=month)

`

1701

1690

`return self._beg_apply_index(i, freqstr)

`

1702

1691

``

1703

1692

``

`@@ -1738,12 +1727,12 @@ def init(self, n=1, normalize=False, month=None):

`

1738

1727

`def _from_name(cls, suffix=None):

`

1739

1728

`kwargs = {}

`

1740

1729

`if suffix:

`

1741

``

`-

kwargs['month'] = _month_to_int[suffix]

`

``

1730

`+

kwargs['month'] = liboffsets._month_to_int[suffix]

`

1742

1731

`return cls(**kwargs)

`

1743

1732

``

1744

1733

`@property

`

1745

1734

`def rule_code(self):

`

1746

``

`-

month = _int_to_month[self.month]

`

``

1735

`+

month = liboffsets._int_to_month[self.month]

`

1747

1736

`return '{prefix}-{month}'.format(prefix=self._prefix, month=month)

`

1748

1737

``

1749

1738

``

`@@ -1784,7 +1773,8 @@ class YearBegin(BeginMixin, YearOffset):

`

1784

1773

`@apply_index_wraps

`

1785

1774

`def apply_index(self, i):

`

1786

1775

`freq_month = 12 if self.month == 1 else self.month - 1

`

1787

``

`-

freqstr = 'A-{month}'.format(month=_int_to_month[freq_month])

`

``

1776

`+

month = liboffsets._int_to_month[freq_month]

`

``

1777

`+

freqstr = 'A-{month}'.format(month=month)

`

1788

1778

`return self._beg_apply_index(i, freqstr)

`

1789

1779

``

1790

1780

``

`@@ -1969,7 +1959,7 @@ def _get_suffix_prefix(self):

`

1969

1959

``

1970

1960

`def get_rule_code_suffix(self):

`

1971

1961

`prefix = self._get_suffix_prefix()

`

1972

``

`-

month = _int_to_month[self.startingMonth]

`

``

1962

`+

month = liboffsets._int_to_month[self.startingMonth]

`

1973

1963

`weekday = _int_to_weekday[self.weekday]

`

1974

1964

`return '{prefix}-{month}-{weekday}'.format(prefix=prefix, month=month,

`

1975

1965

`weekday=weekday)

`

`@@ -1984,7 +1974,7 @@ def _parse_suffix(cls, varion_code, startingMonth_code, weekday_code):

`

1984

1974

`raise ValueError("Unable to parse varion_code: "

`

1985

1975

`"{code}".format(code=varion_code))

`

1986

1976

``

1987

``

`-

startingMonth = _month_to_int[startingMonth_code]

`

``

1977

`+

startingMonth = liboffsets._month_to_int[startingMonth_code]

`

1988

1978

`weekday = _weekday_to_int[weekday_code]

`

1989

1979

``

1990

1980

`return {"weekday": weekday,

`