Skip to content

Commit 80bc2d5

Browse files
committed
TST, MAINT: Add missing components to PR
1 parent 104cab5 commit 80bc2d5

File tree

4 files changed

+49
-26
lines changed

4 files changed

+49
-26
lines changed

doc/source/timeseries.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -1092,9 +1092,9 @@ frequencies. We will refer to these aliases as *offset aliases*
10921092
"BQ", "business quarter endfrequency"
10931093
"QS", "quarter start frequency"
10941094
"BQS", "business quarter start frequency"
1095-
"A", "year end frequency"
1095+
"A, Y", "year end frequency"
10961096
"BA", "business year end frequency"
1097-
"AS", "year start frequency"
1097+
"AS, YS", "year start frequency"
10981098
"BAS", "business year start frequency"
10991099
"BH", "business hour frequency"
11001100
"H", "hourly frequency"

doc/source/whatsnew/v0.21.0.txt

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ Other Enhancements
4040
- :func:`DataFrame.clip()` and :func:`Series.clip()` have gained an ``inplace`` argument. (:issue:`15388`)
4141
- :func:`crosstab` has gained a ``margins_name`` parameter to define the name of the row / column that will contain the totals when ``margins=True``. (:issue:`15972`)
4242
- :func:`DataFrame.select_dtypes` now accepts scalar values for include/exclude as well as list-like. (:issue:`16855`)
43+
- :func:`date_range` now accepts 'YS' in addition to 'AS' as an alias for start of year (:issue:`9313`)
44+
- :func:`date_range` now accepts 'Y' in addition to 'A' as an alias for end of year (:issue:`9313`)
4345

4446
.. _whatsnew_0210.api_breaking:
4547

pandas/tests/indexes/datetimes/test_date_range.py

+24
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,30 @@ def test_date_range_gen_error(self):
3333
rng = date_range('1/1/2000 00:00', '1/1/2000 00:18', freq='5min')
3434
assert len(rng) == 4
3535

36+
@pytest.mark.parametrize("freq", ["AS", "YS"])
37+
def test_begin_year_alias(self, freq):
38+
# see gh-9313
39+
rng = date_range("1/1/2013", "7/1/2017", freq=freq)
40+
exp = pd.DatetimeIndex(["2013-01-01", "2014-01-01",
41+
"2015-01-01", "2016-01-01"], freq=freq)
42+
tm.assert_index_equal(rng, exp)
43+
44+
@pytest.mark.parametrize("freq", ["A", "Y"])
45+
def test_end_year_alias(self, freq):
46+
# see gh-9313
47+
rng = date_range("1/1/2013", "7/1/2017", freq=freq)
48+
exp = pd.DatetimeIndex(["2013-12-31", "2014-12-31",
49+
"2015-12-31", "2016-12-31"], freq=freq)
50+
tm.assert_index_equal(rng, exp)
51+
52+
@pytest.mark.parametrize("freq", ["BA", "BY"])
53+
def test_business_end_year_alias(self, freq):
54+
# see gh-9313
55+
rng = date_range("1/1/2013", "7/1/2017", freq=freq)
56+
exp = pd.DatetimeIndex(["2013-12-31", "2014-12-31",
57+
"2015-12-31", "2016-12-30"], freq=freq)
58+
tm.assert_index_equal(rng, exp)
59+
3660
def test_date_range_negative_freq(self):
3761
# GH 11018
3862
rng = date_range('2011-12-31', freq='-2A', periods=3)

pandas/tseries/frequencies.py

+21-24
Original file line numberDiff line numberDiff line change
@@ -399,10 +399,14 @@ def _get_freq_str(base, mult=1):
399399
'Q': 'Q',
400400
'A': 'A',
401401
'W': 'W',
402-
'M': 'M'
402+
'M': 'M',
403+
'Y': 'A',
404+
'BY': 'A',
405+
'YS': 'A',
406+
'BYS': 'A',
403407
}
404408

405-
need_suffix = ['QS', 'BQ', 'BQS', 'AS', 'BA', 'BAS']
409+
need_suffix = ['QS', 'BQ', 'BQS', 'YS', 'AS', 'BY', 'BA', 'BYS', 'BAS']
406410
for __prefix in need_suffix:
407411
for _m in tslib._MONTHS:
408412
_offset_to_period_map['%s-%s' % (__prefix, _m)] = \
@@ -422,35 +426,18 @@ def get_period_alias(offset_str):
422426
return _offset_to_period_map.get(offset_str, None)
423427

424428

425-
_pure_alias = {
426-
# 'A' is equivalent to 'Y'.
427-
'Y': 'A',
428-
'YS': 'AS',
429-
'BY': 'BA',
430-
'BYS': 'BAS',
431-
'Y-DEC': 'A-DEC',
432-
'Y-JAN': 'A-JAN',
433-
'Y-FEB': 'A-FEB',
434-
'Y-MAR': 'A-MAR',
435-
'Y-APR': 'A-APR',
436-
'Y-MAY': 'A-MAY',
437-
'Y-JUN': 'A-JUN',
438-
'Y-JUL': 'A-JUL',
439-
'Y-AUG': 'A-AUG',
440-
'Y-SEP': 'A-SEP',
441-
'Y-OCT': 'A-OCT',
442-
'Y-NOV': 'A-NOV',
443-
}
444-
445-
446429
_lite_rule_alias = {
447430
'W': 'W-SUN',
448431
'Q': 'Q-DEC',
449432

450433
'A': 'A-DEC', # YearEnd(month=12),
434+
'Y': 'A-DEC',
451435
'AS': 'AS-JAN', # YearBegin(month=1),
436+
'YS': 'AS-JAN',
452437
'BA': 'BA-DEC', # BYearEnd(month=12),
438+
'BY': 'BA-DEC',
453439
'BAS': 'BAS-JAN', # BYearBegin(month=1),
440+
'BYS': 'BAS-JAN',
454441

455442
'Min': 'T',
456443
'min': 'T',
@@ -730,16 +717,26 @@ def get_standard_freq(freq):
730717
_reverse_period_code_map[_v] = _k
731718

732719
# Additional aliases
720+
year_aliases = {}
721+
722+
for k, v in compat.iteritems(_period_code_map):
723+
if k.startswith("A-"):
724+
alias = "Y" + k[1:]
725+
year_aliases[alias] = v
726+
727+
_period_code_map.update(**year_aliases)
728+
del year_aliases
729+
733730
_period_code_map.update({
734731
"Q": 2000, # Quarterly - December year end (default quarterly)
735732
"A": 1000, # Annual
733+
"Y": 1000,
736734
"W": 4000, # Weekly
737735
"C": 5000, # Custom Business Day
738736
})
739737

740738

741739
def _period_str_to_code(freqstr):
742-
freqstr = _pure_alias.get(freqstr, freqstr)
743740
freqstr = _lite_rule_alias.get(freqstr, freqstr)
744741

745742
if freqstr not in _dont_uppercase:

0 commit comments

Comments
 (0)