Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
41 changes: 36 additions & 5 deletions Doc/library/calendar.rst
Original file line number Diff line number Diff line change
Expand Up @@ -493,9 +493,10 @@ The :mod:`calendar` module exports the following data attributes:

.. data:: month_name

A sequence that represents the months of the year in the current locale. This
follows normal convention of January being month number 1, so it has a length of
13 and ``month_name[0]`` is the empty string.
A sequence that represents the months of the year in the current locale
in the grammatical form used when the month is part of a complete date.
This follows normal convention of January being month number 1, so it has
a length of 13 and ``month_name[0]`` is the empty string.

>>> import calendar
>>> list(calendar.month_name)
Expand All @@ -505,13 +506,43 @@ The :mod:`calendar` module exports the following data attributes:
.. data:: month_abbr

A sequence that represents the abbreviated months of the year in the current
locale. This follows normal convention of January being month number 1, so it
has a length of 13 and ``month_abbr[0]`` is the empty string.
locale in the grammatical form used when the month is part of a complete date.
This follows normal convention of January being month number 1, so it has
a length of 13 and ``month_abbr[0]`` is the empty string.

>>> import calendar
>>> list(calendar.month_abbr)
['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']


.. data:: alt_month_name

A sequence that represents the months of the year in the current locale
in the grammatical form used when the month is named by itself if the locale
provides one. If the locale does not supply an alternative form, it falls back
to the behavior of :data:`month_name`.

>>> import calendar
>>> list(calendar.alt_month_name)
['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']

.. versionadded:: next


.. data:: alt_month_abbr

A sequence that represents the abbreviated months of the year in the current
locale in the grammatical form used when the month is named by itself if the
locale provides one. If the locale does not supply an alternative form, it falls
back to the behavior of :data:`month_abbr`.

>>> import calendar
>>> list(calendar.alt_month_abbr)
['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

.. versionadded:: next


.. data:: JANUARY
FEBRUARY
MARCH
Expand Down
30 changes: 25 additions & 5 deletions Lib/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
"firstweekday", "isleap", "leapdays", "weekday", "monthrange",
"monthcalendar", "prmonth", "month", "prcal", "calendar",
"timegm", "month_name", "month_abbr", "day_name", "day_abbr",
"Calendar", "TextCalendar", "HTMLCalendar", "LocaleTextCalendar",
"timegm", "month_name", "month_abbr", "alt_month_name",
"alt_month_abbr", "day_name", "day_abbr", "Calendar",
"TextCalendar", "HTMLCalendar", "LocaleTextCalendar",
"LocaleHTMLCalendar", "weekheader",
"Day", "Month", "JANUARY", "FEBRUARY", "MARCH",
"APRIL", "MAY", "JUNE", "JULY",
Expand Down Expand Up @@ -139,6 +140,25 @@ def __len__(self):
month_name = _localized_month('%B')
month_abbr = _localized_month('%b')

# Check if the platform supports %OB and %Ob specifiers
def _supports_alternative_month_names():
try:
datetime.date(2001, 1, 1).strftime('%OB')
datetime.date(2001, 1, 1).strftime('%Ob')
except ValueError:
return False
return True

# On platforms that support the %OB and %Ob specifiers, it is used to get the
# standalone form of the month name. This is required for some languages
# such as Greek, Slavic, and Baltic languages.
if _supports_alternative_month_names():
alt_month_name = _localized_month('%OB')
alt_month_abbr = _localized_month('%Ob')
else:
alt_month_name = month_name
alt_month_abbr = month_abbr


def isleap(year):
"""Return True for leap years, False for non-leap years."""
Expand Down Expand Up @@ -377,7 +397,7 @@ def formatmonthname(self, theyear, themonth, width, withyear=True):
"""
_validate_month(themonth)

s = month_name[themonth]
s = alt_month_name[themonth]
if withyear:
s = "%s %r" % (s, theyear)
return s.center(width)
Expand Down Expand Up @@ -510,9 +530,9 @@ def formatmonthname(self, theyear, themonth, withyear=True):
"""
_validate_month(themonth)
if withyear:
s = '%s %s' % (month_name[themonth], theyear)
s = '%s %s' % (alt_month_name[themonth], theyear)
else:
s = '%s' % month_name[themonth]
s = alt_month_name[themonth]
return '<tr><th colspan="7" class="%s">%s</th></tr>' % (
self.cssclass_month_head, s)

Expand Down
10 changes: 9 additions & 1 deletion Lib/test/test_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,8 @@ def test_days(self):
self.assertEqual(value[::-1], list(reversed(value)))

def test_months(self):
for attr in "month_name", "month_abbr":
for attr in ["month_name", "month_abbr", "alt_month_name",
"alt_month_abbr"]:
value = getattr(calendar, attr)
self.assertEqual(len(value), 13)
self.assertEqual(len(value[:]), 13)
Expand All @@ -556,6 +557,13 @@ def test_months(self):
# verify it "acts like a sequence" in two forms of iteration
self.assertEqual(value[::-1], list(reversed(value)))

def test_alt_month_name_and_abbr(self):
# Ensure that the alternate month names and abbreviations are equal
# to the regular month names and abbreviations for the "C" locale.
with calendar.different_locale("C"):
self.assertListEqual(list(calendar.month_name), list(calendar.alt_month_name))
self.assertListEqual(list(calendar.month_abbr), list(calendar.alt_month_abbr))

def test_locale_text_calendar(self):
try:
cal = calendar.LocaleTextCalendar(locale='')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Add :func:`calendar.alt_month_name` and :func:`calendar.alt_month_abbr` to
provide alternative month names and abbreviations for the current locale
when available. These are used when the month is named by itself, such as in
a standalone date.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix :class:`calendar.TextCalendar` and :class:`calendar.HTMLCalendar` and
:mod:`calendar` CLI to display month names in the nominative case if
provided by the locale.
Loading