Календарь: названия дня/месяца в определенной локали

Я играю с модулем календаря Python, который находится в стандартной библиотеке. В основном мне нужен список всех дней месяца, например:

>>> import calendar
>>> calobject = calendar.monthcalendar(2012, 10)
>>> print calobject
[[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14], [15, 16, 17, 18, 19, 20, 21], [22, 23, 24, 25, 26, 27, 28], [29, 30, 31, 0, 0, 0, 0]]

Теперь мне также нужны названия месяцев и дней в определенной локали. Я не нашел способа получить их из самого calobject, но мне удалось получить их так:

>>> import calendar
>>> calobject = calendar.LocaleTextCalendar(calendar.MONDAY, 'de_DE')
>>> calobject.formatmonth(2012, 10)
'    Oktober 2012\nMo Di Mi Do Fr Sa So\n 1  2  3  4  5  6  7\n 8  9 10 11 12 13 14\n15 16 17 18 19 20 21\n22 23 24 25 26 27 28\n29 30 31\n'

Итак, Oktober — это de_DE название октября. Отлично. Информация должна быть там. Мне интересно, могу ли я каким-то образом получить доступ к этому названию месяца на простом объекте calendar вместо объекта calendar.LocaleTextCalendar. Первый пример (со списком) действительно то, что мне нужно, и мне не нравится идея создавать два объекта календаря для получения локализованных имен.

У кого-нибудь есть умная идея?


person Daniel    schedule 23.10.2012    source источник
comment
Я думаю, вы сможете сделать: calendar.month_name[month], где month — целое число, представляющее месяц.   -  person Alok Singhal    schedule 23.10.2012
comment
Спасибо Алок. Да, но тогда это в локали по умолчанию   -  person Daniel    schedule 23.10.2012


Ответы (3)


Это из исходного кода модуля calendar:

def formatmonthname(self, theyear, themonth, width, withyear=True):
    with TimeEncoding(self.locale) as encoding:
        s = month_name[themonth]
        if encoding is not None:
            s = s.decode(encoding)
        if withyear:
            s = "%s %r" % (s, theyear)
        return s.center(width)

TimeEncoding и month_name можно импортировать из модуля calendar. Это дает следующий метод:

from calendar import TimeEncoding, month_name

def get_month_name(month_no, locale):
    with TimeEncoding(locale) as encoding:
        s = month_name[month_no]
        if encoding is not None:
            s = s.decode(encoding)
        return s

print get_month_name(3, "nb_NO.UTF-8")

Для меня шаг декодирования не нужен, просто печать month_name[3] в контексте TimeEncoding напечатает «марс», что по-норвежски означает «март».

Для будних дней есть аналогичный метод, использующий словари day_name и day_abbr:

from calendar import TimeEncoding, day_name, day_abbr

def get_day_name(day_no, locale, short=False):
    with TimeEncoding(locale) as encoding:
        if short:
            s = day_abbr[day_no]
        else:
            s = day_name[day_no]
        if encoding is not None:
            s = s.decode(encoding)
        return s
person Lauritz V. Thaulow    schedule 23.10.2012
comment
Спасибо лазир. Что ж, это работает. Я надеялся, что есть более простой способ добиться этого. Я понял, что также могу импортировать day_name. Я думаю, что я буду жестко закодировать имена для месяцев и дней (две строки кода). Нам он нужен только на немецком языке, а названия месяцев/дней вряд ли изменятся в ближайшие несколько лет. Спасибо хоть. - person Daniel; 23.10.2012
comment
@ Даниэль Нет проблем. Даже если вам это не нужно, теперь ответ здесь для следующего человека, которому это нужно. - person Lauritz V. Thaulow; 23.10.2012
comment
Да. Это слишком сложно. Я подумал, что есть простой способ получить доступ к этой информации, например настроить экземпляр календаря с определенной локалью. - person Daniel; 23.10.2012
comment
В pyhton3 TimeEncoding переименовывается в different_locale. Это также работает немного по-другому, вызов decode больше не нужен. - person jjmurre; 20.07.2017

Ха! Найден простой способ получить локализованные названия дней/месяцев:

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
'de_DE'
>>> import calendar
>>> calendar.month_name[10]
'Oktober'
>>> calendar.day_name[1]
'Dienstag'
person Daniel    schedule 23.10.2012
comment
Это просто урезанная версия моего ответа. Контекст TimeEncoding — это просто способ временной установки локали. Если вы хотите, чтобы это было постоянным, можно напрямую вызвать setlocale. Я предполагаю, что шаг кодирования необходим только в том случае, если у вас есть символы Юникода в названиях месяцев/дней, что, похоже, не относится к немецкому языку. - person Lauritz V. Thaulow; 23.10.2012
comment
Ох, ну ладно. Да, у нас есть символы Юникода: ››› calendar.month_name[3] 'M\xc3\xa4rz' - person Daniel; 23.10.2012

Вот месячная часть ответа Лаурица, обновленная для Python 3:

from calendar import month_name, different_locale
def get_month_name(month_no, locale):
    with different_locale(locale):
        return month_name[month_no])
person Thomas Parslow    schedule 04.06.2018
comment
Я получаю предупреждение 'different_locale' is not declared in __all__. Кроме того, нигде нет документации по different_locale. - person Tobias Feil; 12.06.2019
comment
Синтаксическая ошибка/опечатка здесь, надо убрать последнюю ) - person Håkon T.; 04.11.2020