Skip to content

Commit 5b16332

Browse files
authored
DEPR offsets: rename 'SM' to 'SME' (#56050)
1 parent 4514636 commit 5b16332

File tree

8 files changed

+60
-36
lines changed

8 files changed

+60
-36
lines changed

doc/source/user_guide/timeseries.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ into ``freq`` keyword arguments. The available date offsets and associated frequ
882882
:class:`~pandas.tseries.offsets.BMonthBegin` or :class:`~pandas.tseries.offsets.BusinessMonthBegin`, ``'BMS'``, "business month begin"
883883
:class:`~pandas.tseries.offsets.CBMonthEnd` or :class:`~pandas.tseries.offsets.CustomBusinessMonthEnd`, ``'CBME'``, "custom business month end"
884884
:class:`~pandas.tseries.offsets.CBMonthBegin` or :class:`~pandas.tseries.offsets.CustomBusinessMonthBegin`, ``'CBMS'``, "custom business month begin"
885-
:class:`~pandas.tseries.offsets.SemiMonthEnd`, ``'SM'``, "15th (or other day_of_month) and calendar month end"
885+
:class:`~pandas.tseries.offsets.SemiMonthEnd`, ``'SME'``, "15th (or other day_of_month) and calendar month end"
886886
:class:`~pandas.tseries.offsets.SemiMonthBegin`, ``'SMS'``, "15th (or other day_of_month) and calendar month begin"
887887
:class:`~pandas.tseries.offsets.QuarterEnd`, ``'QE'``, "calendar quarter end"
888888
:class:`~pandas.tseries.offsets.QuarterBegin`, ``'QS'``, "calendar quarter begin"
@@ -1241,7 +1241,7 @@ frequencies. We will refer to these aliases as *offset aliases*.
12411241
"D", "calendar day frequency"
12421242
"W", "weekly frequency"
12431243
"ME", "month end frequency"
1244-
"SM", "semi-month end frequency (15th and end of month)"
1244+
"SME", "semi-month end frequency (15th and end of month)"
12451245
"BME", "business month end frequency"
12461246
"CBME", "custom business month end frequency"
12471247
"MS", "month start frequency"

doc/source/whatsnew/v0.19.0.rst

+10-6
Original file line numberDiff line numberDiff line change
@@ -329,11 +329,13 @@ These provide date offsets anchored (by default) to the 15th and end of month, a
329329
330330
**SemiMonthEnd**:
331331

332-
.. ipython:: python
332+
.. code-block:: python
333333
334-
pd.Timestamp("2016-01-01") + SemiMonthEnd()
334+
In [46]: pd.Timestamp("2016-01-01") + SemiMonthEnd()
335+
Out[46]: Timestamp('2016-01-15 00:00:00')
335336
336-
pd.date_range("2015-01-01", freq="SM", periods=4)
337+
In [47]: pd.date_range("2015-01-01", freq="SM", periods=4)
338+
Out[47]: DatetimeIndex(['2015-01-15', '2015-01-31', '2015-02-15', '2015-02-28'], dtype='datetime64[ns]', freq='SM-15')
337339
338340
**SemiMonthBegin**:
339341

@@ -345,11 +347,13 @@ These provide date offsets anchored (by default) to the 15th and end of month, a
345347
346348
Using the anchoring suffix, you can also specify the day of month to use instead of the 15th.
347349

348-
.. ipython:: python
350+
.. code-block:: python
349351
350-
pd.date_range("2015-01-01", freq="SMS-16", periods=4)
352+
In [50]: pd.date_range("2015-01-01", freq="SMS-16", periods=4)
353+
Out[50]: DatetimeIndex(['2015-01-01', '2015-01-16', '2015-02-01', '2015-02-16'], dtype='datetime64[ns]', freq='SMS-16')
351354
352-
pd.date_range("2015-01-01", freq="SM-14", periods=4)
355+
In [51]: pd.date_range("2015-01-01", freq="SM-14", periods=4)
356+
Out[51]: DatetimeIndex(['2015-01-14', '2015-01-31', '2015-02-14', '2015-02-28'], dtype='datetime64[ns]', freq='SM-14')
353357
354358
.. _whatsnew_0190.enhancements.index:
355359

doc/source/whatsnew/v2.2.0.rst

+7-3
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,17 @@ Other API changes
233233
Deprecations
234234
~~~~~~~~~~~~
235235

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

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

241241
- ``M`` (month end) has been renamed ``ME`` for offsets
242+
- ``SM`` (semi month end) has been renamed ``SME`` for offsets
243+
- ``BM`` (business month end) has been renamed ``BME`` for offsets
244+
- ``CBM`` (custom business month end) has been renamed ``CBME`` for offsets
242245
- ``Q`` (quarter end) has been renamed ``QE`` for offsets
246+
- ``BQ`` (business quarter end) has been renamed ``BQE`` for offsets
243247
- ``Y`` (year end) has been renamed ``YE`` for offsets
244248

245249
For example:
@@ -291,7 +295,7 @@ Other Deprecations
291295
- 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`)
292296
- 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`)
293297
- Deprecated string ``BQ`` denoting frequency in :class:`BQuarterEnd` (:issue:`52064`)
294-
- Deprecated strings ``BM``, and ``CBM`` denoting frequencies in :class:`BusinessMonthEnd`, :class:`CustomBusinessMonthEnd` (:issue:`52064`)
298+
- Deprecated strings ``BM``, ``CBM``, and ``SM`` denoting frequencies in :class:`BusinessMonthEnd`, :class:`CustomBusinessMonthEnd, :class:`SemiMonthEnd` (:issue:`52064`)
295299
- Deprecated strings ``H``, ``BH``, and ``CBH`` denoting frequencies in :class:`Hour`, :class:`BusinessHour`, :class:`CustomBusinessHour` (:issue:`52536`)
296300
- Deprecated strings ``H``, ``S``, ``U``, and ``N`` denoting units in :func:`to_timedelta` (:issue:`52536`)
297301
- Deprecated strings ``H``, ``T``, ``S``, ``L``, ``U``, and ``N`` denoting units in :class:`Timedelta` (:issue:`52536`)

pandas/_libs/tslibs/dtypes.pyx

+2-2
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ OFFSET_TO_PERIOD_FREQSTR: dict = {
175175
"WEEKDAY": "D",
176176
"EOM": "M",
177177
"BME": "M",
178+
"SME": "M",
178179
"BQS": "Q",
179180
"QS": "Q",
180181
"BQE": "Q",
@@ -275,6 +276,7 @@ cdef dict c_OFFSET_DEPR_FREQSTR = {
275276
"A-NOV": "YE-NOV",
276277
"BM": "BME",
277278
"CBM": "CBME",
279+
"SM": "SME",
278280
"BQ": "BQE",
279281
"BQ-DEC": "BQE-DEC",
280282
"BQ-JAN": "BQE-JAN",
@@ -358,8 +360,6 @@ cdef dict c_DEPR_ABBREVS = {
358360
"BAS-SEP": "BYS-SEP",
359361
"BAS-OCT": "BYS-OCT",
360362
"BAS-NOV": "BYS-NOV",
361-
"BM": "BME",
362-
"CBM": "CBME",
363363
"H": "h",
364364
"BH": "bh",
365365
"CBH": "cbh",

pandas/_libs/tslibs/offsets.pyx

+2-2
Original file line numberDiff line numberDiff line change
@@ -3129,7 +3129,7 @@ cdef class SemiMonthEnd(SemiMonthOffset):
31293129
>>> pd.offsets.SemiMonthEnd().rollforward(ts)
31303130
Timestamp('2022-01-15 00:00:00')
31313131
"""
3132-
_prefix = "SM"
3132+
_prefix = "SME"
31333133
_min_day_of_month = 1
31343134

31353135
def is_on_offset(self, dt: datetime) -> bool:
@@ -4549,7 +4549,7 @@ prefix_mapping = {
45494549
MonthEnd, # 'ME'
45504550
MonthBegin, # 'MS'
45514551
Nano, # 'ns'
4552-
SemiMonthEnd, # 'SM'
4552+
SemiMonthEnd, # 'SME'
45534553
SemiMonthBegin, # 'SMS'
45544554
Week, # 'W'
45554555
Second, # 's'

pandas/tests/indexes/datetimes/test_date_range.py

+14-6
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,20 @@ def test_date_range_float_periods(self):
145145
exp = date_range("1/1/2000", periods=10)
146146
tm.assert_index_equal(rng, exp)
147147

148-
def test_date_range_frequency_M_deprecated(self):
149-
depr_msg = "'M' is deprecated, please use 'ME' instead."
148+
@pytest.mark.parametrize(
149+
"freq,freq_depr",
150+
[
151+
("2ME", "2M"),
152+
("2SME", "2SM"),
153+
],
154+
)
155+
def test_date_range_frequency_M_SM_deprecated(self, freq, freq_depr):
156+
# GH#52064
157+
depr_msg = f"'{freq_depr[1:]}' is deprecated, please use '{freq[1:]}' instead."
150158

151-
expected = date_range("1/1/2000", periods=4, freq="2ME")
159+
expected = date_range("1/1/2000", periods=4, freq=freq)
152160
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
153-
result = date_range("1/1/2000", periods=4, freq="2M")
161+
result = date_range("1/1/2000", periods=4, freq=freq_depr)
154162
tm.assert_index_equal(result, expected)
155163

156164
def test_date_range_tuple_freq_raises(self):
@@ -1624,8 +1632,8 @@ def test_date_range_semi_month_end(self, unit):
16241632
datetime(2008, 12, 31),
16251633
]
16261634
# ensure generating a range with DatetimeIndex gives same result
1627-
result = date_range(start=dates[0], end=dates[-1], freq="SM", unit=unit)
1628-
exp = DatetimeIndex(dates, dtype=f"M8[{unit}]", freq="SM")
1635+
result = date_range(start=dates[0], end=dates[-1], freq="SME", unit=unit)
1636+
exp = DatetimeIndex(dates, dtype=f"M8[{unit}]", freq="SME")
16291637
tm.assert_index_equal(result, exp)
16301638

16311639
def test_date_range_week_of_month(self, unit):

pandas/tests/indexes/period/test_period.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,19 @@ def test_map(self):
281281
exp = Index([x.ordinal for x in index])
282282
tm.assert_index_equal(result, exp)
283283

284-
def test_period_index_frequency_ME_error_message(self):
285-
msg = "for Period, please use 'M' instead of 'ME'"
284+
@pytest.mark.parametrize(
285+
"freq,freq_depr",
286+
[
287+
("2M", "2ME"),
288+
("2SM", "2SME"),
289+
],
290+
)
291+
def test_period_index_frequency_ME_SME_error_message(self, freq, freq_depr):
292+
# GH#52064
293+
msg = f"for Period, please use '{freq[1:]}' instead of '{freq_depr[1:]}'"
286294

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

290298
def test_H_deprecated_from_time_series(self):
291299
# GH#52536

pandas/tests/tslibs/test_to_offset.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
("1s0.25ms", offsets.Micro(1000250)),
2727
("1s0.25ms", offsets.Micro(1000250)),
2828
("2800ns", offsets.Nano(2800)),
29-
("2SM", offsets.SemiMonthEnd(2)),
30-
("2SM-16", offsets.SemiMonthEnd(2, day_of_month=16)),
29+
("2SME", offsets.SemiMonthEnd(2)),
30+
("2SME-16", offsets.SemiMonthEnd(2, day_of_month=16)),
3131
("2SMS-14", offsets.SemiMonthBegin(2, day_of_month=14)),
3232
("2SMS-15", offsets.SemiMonthBegin(2)),
3333
],
@@ -38,7 +38,7 @@ def test_to_offset(freq_input, expected):
3838

3939

4040
@pytest.mark.parametrize(
41-
"freqstr,expected", [("-1s", -1), ("-2SM", -2), ("-1SMS", -1), ("-5min10s", -310)]
41+
"freqstr,expected", [("-1s", -1), ("-2SME", -2), ("-1SMS", -1), ("-5min10s", -310)]
4242
)
4343
def test_to_offset_negative(freqstr, expected):
4444
result = to_offset(freqstr)
@@ -66,12 +66,12 @@ def test_to_offset_negative(freqstr, expected):
6666
"+d",
6767
"-m",
6868
# Invalid shortcut anchors.
69-
"SM-0",
70-
"SM-28",
71-
"SM-29",
72-
"SM-FOO",
69+
"SME-0",
70+
"SME-28",
71+
"SME-29",
72+
"SME-FOO",
7373
"BSM",
74-
"SM--1",
74+
"SME--1",
7575
"SMS-1",
7676
"SMS-28",
7777
"SMS-30",
@@ -161,10 +161,10 @@ def test_to_offset_pd_timedelta(kwargs, expected):
161161
("QE", offsets.QuarterEnd(startingMonth=12)),
162162
("QE-DEC", offsets.QuarterEnd(startingMonth=12)),
163163
("QE-MAY", offsets.QuarterEnd(startingMonth=5)),
164-
("SM", offsets.SemiMonthEnd(day_of_month=15)),
165-
("SM-15", offsets.SemiMonthEnd(day_of_month=15)),
166-
("SM-1", offsets.SemiMonthEnd(day_of_month=1)),
167-
("SM-27", offsets.SemiMonthEnd(day_of_month=27)),
164+
("SME", offsets.SemiMonthEnd(day_of_month=15)),
165+
("SME-15", offsets.SemiMonthEnd(day_of_month=15)),
166+
("SME-1", offsets.SemiMonthEnd(day_of_month=1)),
167+
("SME-27", offsets.SemiMonthEnd(day_of_month=27)),
168168
("SMS-2", offsets.SemiMonthBegin(day_of_month=2)),
169169
("SMS-27", offsets.SemiMonthBegin(day_of_month=27)),
170170
],

0 commit comments

Comments
 (0)