Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEPR offsets: rename 'SM' to 'SME' #56050

Merged
merged 4 commits into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/source/user_guide/timeseries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ into ``freq`` keyword arguments. The available date offsets and associated frequ
:class:`~pandas.tseries.offsets.BMonthBegin` or :class:`~pandas.tseries.offsets.BusinessMonthBegin`, ``'BMS'``, "business month begin"
:class:`~pandas.tseries.offsets.CBMonthEnd` or :class:`~pandas.tseries.offsets.CustomBusinessMonthEnd`, ``'CBME'``, "custom business month end"
:class:`~pandas.tseries.offsets.CBMonthBegin` or :class:`~pandas.tseries.offsets.CustomBusinessMonthBegin`, ``'CBMS'``, "custom business month begin"
:class:`~pandas.tseries.offsets.SemiMonthEnd`, ``'SM'``, "15th (or other day_of_month) and calendar month end"
:class:`~pandas.tseries.offsets.SemiMonthEnd`, ``'SME'``, "15th (or other day_of_month) and calendar month end"
:class:`~pandas.tseries.offsets.SemiMonthBegin`, ``'SMS'``, "15th (or other day_of_month) and calendar month begin"
:class:`~pandas.tseries.offsets.QuarterEnd`, ``'QE'``, "calendar quarter end"
:class:`~pandas.tseries.offsets.QuarterBegin`, ``'QS'``, "calendar quarter begin"
Expand Down Expand Up @@ -1241,7 +1241,7 @@ frequencies. We will refer to these aliases as *offset aliases*.
"D", "calendar day frequency"
"W", "weekly frequency"
"ME", "month end frequency"
"SM", "semi-month end frequency (15th and end of month)"
"SME", "semi-month end frequency (15th and end of month)"
"BME", "business month end frequency"
"CBME", "custom business month end frequency"
"MS", "month start frequency"
Expand Down
16 changes: 10 additions & 6 deletions doc/source/whatsnew/v0.19.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,13 @@ These provide date offsets anchored (by default) to the 15th and end of month, a

**SemiMonthEnd**:

.. ipython:: python
.. code-block:: python

pd.Timestamp("2016-01-01") + SemiMonthEnd()
In [46]: pd.Timestamp("2016-01-01") + SemiMonthEnd()
Out[46]: Timestamp('2016-01-15 00:00:00')

pd.date_range("2015-01-01", freq="SM", periods=4)
In [47]: pd.date_range("2015-01-01", freq="SM", periods=4)
Out[47]: DatetimeIndex(['2015-01-15', '2015-01-31', '2015-02-15', '2015-02-28'], dtype='datetime64[ns]', freq='SM-15')

**SemiMonthBegin**:

Expand All @@ -345,11 +347,13 @@ These provide date offsets anchored (by default) to the 15th and end of month, a

Using the anchoring suffix, you can also specify the day of month to use instead of the 15th.

.. ipython:: python
.. code-block:: python

pd.date_range("2015-01-01", freq="SMS-16", periods=4)
In [50]: pd.date_range("2015-01-01", freq="SMS-16", periods=4)
Out[50]: DatetimeIndex(['2015-01-01', '2015-01-16', '2015-02-01', '2015-02-16'], dtype='datetime64[ns]', freq='SMS-16')

pd.date_range("2015-01-01", freq="SM-14", periods=4)
In [51]: pd.date_range("2015-01-01", freq="SM-14", periods=4)
Out[51]: DatetimeIndex(['2015-01-14', '2015-01-31', '2015-02-14', '2015-02-28'], dtype='datetime64[ns]', freq='SM-14')

.. _whatsnew_0190.enhancements.index:

Expand Down
10 changes: 7 additions & 3 deletions doc/source/whatsnew/v2.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,17 @@ Other API changes
Deprecations
~~~~~~~~~~~~

Deprecate aliases ``M``, ``Q``, and ``Y`` in favour of ``ME``, ``QE``, and ``YE`` for offsets
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Deprecate aliases ``M``, ``SM``, ``BM``, ``CBM``, ``Q``, ``BQ``, and ``Y`` in favour of ``ME``, ``SME``, ``BME``, ``CBME``, ``QE``, ``BQE``, and ``YE`` for offsets
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Deprecated the following frequency aliases (:issue:`9586`):

- ``M`` (month end) has been renamed ``ME`` for offsets
- ``SM`` (semi month end) has been renamed ``SME`` for offsets
- ``BM`` (business month end) has been renamed ``BME`` for offsets
- ``CBM`` (custom business month end) has been renamed ``CBME`` for offsets
- ``Q`` (quarter end) has been renamed ``QE`` for offsets
- ``BQ`` (business quarter end) has been renamed ``BQE`` for offsets
- ``Y`` (year end) has been renamed ``YE`` for offsets

For example:
Expand Down Expand Up @@ -291,7 +295,7 @@ Other Deprecations
- Deprecated string ``BAS`` denoting frequency in :class:`BYearBegin` and strings ``BAS-DEC``, ``BAS-JAN``, etc. denoting annual frequencies with various fiscal year starts (:issue:`54275`)
- Deprecated string ``BA`` denoting frequency in :class:`BYearEnd` and strings ``BA-DEC``, ``BA-JAN``, etc. denoting annual frequencies with various fiscal year ends (:issue:`54275`)
- Deprecated string ``BQ`` denoting frequency in :class:`BQuarterEnd` (:issue:`52064`)
- Deprecated strings ``BM``, and ``CBM`` denoting frequencies in :class:`BusinessMonthEnd`, :class:`CustomBusinessMonthEnd` (:issue:`52064`)
- Deprecated strings ``BM``, ``CBM``, and ``SM`` denoting frequencies in :class:`BusinessMonthEnd`, :class:`CustomBusinessMonthEnd, :class:`SemiMonthEnd` (:issue:`52064`)
- Deprecated strings ``H``, ``BH``, and ``CBH`` denoting frequencies in :class:`Hour`, :class:`BusinessHour`, :class:`CustomBusinessHour` (:issue:`52536`)
- Deprecated strings ``H``, ``S``, ``U``, and ``N`` denoting units in :func:`to_timedelta` (:issue:`52536`)
- Deprecated strings ``H``, ``T``, ``S``, ``L``, ``U``, and ``N`` denoting units in :class:`Timedelta` (:issue:`52536`)
Expand Down
4 changes: 2 additions & 2 deletions pandas/_libs/tslibs/dtypes.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ OFFSET_TO_PERIOD_FREQSTR: dict = {
"WEEKDAY": "D",
"EOM": "M",
"BME": "M",
"SME": "M",
"BQS": "Q",
"QS": "Q",
"BQE": "Q",
Expand Down Expand Up @@ -275,6 +276,7 @@ cdef dict c_OFFSET_DEPR_FREQSTR = {
"A-NOV": "YE-NOV",
"BM": "BME",
"CBM": "CBME",
"SM": "SME",
"BQ": "BQE",
"BQ-DEC": "BQE-DEC",
"BQ-JAN": "BQE-JAN",
Expand Down Expand Up @@ -358,8 +360,6 @@ cdef dict c_DEPR_ABBREVS = {
"BAS-SEP": "BYS-SEP",
"BAS-OCT": "BYS-OCT",
"BAS-NOV": "BYS-NOV",
"BM": "BME",
"CBM": "CBME",
"H": "h",
"BH": "bh",
"CBH": "cbh",
Expand Down
4 changes: 2 additions & 2 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3129,7 +3129,7 @@ cdef class SemiMonthEnd(SemiMonthOffset):
>>> pd.offsets.SemiMonthEnd().rollforward(ts)
Timestamp('2022-01-15 00:00:00')
"""
_prefix = "SM"
_prefix = "SME"
_min_day_of_month = 1

def is_on_offset(self, dt: datetime) -> bool:
Expand Down Expand Up @@ -4549,7 +4549,7 @@ prefix_mapping = {
MonthEnd, # 'ME'
MonthBegin, # 'MS'
Nano, # 'ns'
SemiMonthEnd, # 'SM'
SemiMonthEnd, # 'SME'
SemiMonthBegin, # 'SMS'
Week, # 'W'
Second, # 's'
Expand Down
20 changes: 14 additions & 6 deletions pandas/tests/indexes/datetimes/test_date_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,20 @@ def test_date_range_float_periods(self):
exp = date_range("1/1/2000", periods=10)
tm.assert_index_equal(rng, exp)

def test_date_range_frequency_M_deprecated(self):
depr_msg = "'M' is deprecated, please use 'ME' instead."
@pytest.mark.parametrize(
"freq,freq_depr",
[
("2ME", "2M"),
("2SME", "2SM"),
],
)
def test_date_range_frequency_M_SM_deprecated(self, freq, freq_depr):
# GH#52064
depr_msg = f"'{freq_depr[1:]}' is deprecated, please use '{freq[1:]}' instead."

expected = date_range("1/1/2000", periods=4, freq="2ME")
expected = date_range("1/1/2000", periods=4, freq=freq)
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
result = date_range("1/1/2000", periods=4, freq="2M")
result = date_range("1/1/2000", periods=4, freq=freq_depr)
tm.assert_index_equal(result, expected)

def test_date_range_tuple_freq_raises(self):
Expand Down Expand Up @@ -1624,8 +1632,8 @@ def test_date_range_semi_month_end(self, unit):
datetime(2008, 12, 31),
]
# ensure generating a range with DatetimeIndex gives same result
result = date_range(start=dates[0], end=dates[-1], freq="SM", unit=unit)
exp = DatetimeIndex(dates, dtype=f"M8[{unit}]", freq="SM")
result = date_range(start=dates[0], end=dates[-1], freq="SME", unit=unit)
exp = DatetimeIndex(dates, dtype=f"M8[{unit}]", freq="SME")
tm.assert_index_equal(result, exp)

def test_date_range_week_of_month(self, unit):
Expand Down
14 changes: 11 additions & 3 deletions pandas/tests/indexes/period/test_period.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,19 @@ def test_map(self):
exp = Index([x.ordinal for x in index])
tm.assert_index_equal(result, exp)

def test_period_index_frequency_ME_error_message(self):
msg = "for Period, please use 'M' instead of 'ME'"
@pytest.mark.parametrize(
"freq,freq_depr",
[
("2M", "2ME"),
("2SM", "2SME"),
],
)
def test_period_index_frequency_ME_SME_error_message(self, freq, freq_depr):
# GH#52064
msg = f"for Period, please use '{freq[1:]}' instead of '{freq_depr[1:]}'"

with pytest.raises(ValueError, match=msg):
PeriodIndex(["2020-01-01", "2020-01-02"], freq="2ME")
PeriodIndex(["2020-01-01", "2020-01-02"], freq=freq_depr)

def test_H_deprecated_from_time_series(self):
# GH#52536
Expand Down
24 changes: 12 additions & 12 deletions pandas/tests/tslibs/test_to_offset.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
("1s0.25ms", offsets.Micro(1000250)),
("1s0.25ms", offsets.Micro(1000250)),
("2800ns", offsets.Nano(2800)),
("2SM", offsets.SemiMonthEnd(2)),
("2SM-16", offsets.SemiMonthEnd(2, day_of_month=16)),
("2SME", offsets.SemiMonthEnd(2)),
("2SME-16", offsets.SemiMonthEnd(2, day_of_month=16)),
("2SMS-14", offsets.SemiMonthBegin(2, day_of_month=14)),
("2SMS-15", offsets.SemiMonthBegin(2)),
],
Expand All @@ -38,7 +38,7 @@ def test_to_offset(freq_input, expected):


@pytest.mark.parametrize(
"freqstr,expected", [("-1s", -1), ("-2SM", -2), ("-1SMS", -1), ("-5min10s", -310)]
"freqstr,expected", [("-1s", -1), ("-2SME", -2), ("-1SMS", -1), ("-5min10s", -310)]
)
def test_to_offset_negative(freqstr, expected):
result = to_offset(freqstr)
Expand Down Expand Up @@ -66,12 +66,12 @@ def test_to_offset_negative(freqstr, expected):
"+d",
"-m",
# Invalid shortcut anchors.
"SM-0",
"SM-28",
"SM-29",
"SM-FOO",
"SME-0",
"SME-28",
"SME-29",
"SME-FOO",
"BSM",
"SM--1",
"SME--1",
"SMS-1",
"SMS-28",
"SMS-30",
Expand Down Expand Up @@ -161,10 +161,10 @@ def test_to_offset_pd_timedelta(kwargs, expected):
("QE", offsets.QuarterEnd(startingMonth=12)),
("QE-DEC", offsets.QuarterEnd(startingMonth=12)),
("QE-MAY", offsets.QuarterEnd(startingMonth=5)),
("SM", offsets.SemiMonthEnd(day_of_month=15)),
("SM-15", offsets.SemiMonthEnd(day_of_month=15)),
("SM-1", offsets.SemiMonthEnd(day_of_month=1)),
("SM-27", offsets.SemiMonthEnd(day_of_month=27)),
("SME", offsets.SemiMonthEnd(day_of_month=15)),
("SME-15", offsets.SemiMonthEnd(day_of_month=15)),
("SME-1", offsets.SemiMonthEnd(day_of_month=1)),
("SME-27", offsets.SemiMonthEnd(day_of_month=27)),
("SMS-2", offsets.SemiMonthBegin(day_of_month=2)),
("SMS-27", offsets.SemiMonthBegin(day_of_month=27)),
],
Expand Down
Loading