日期和时间

在Python中使用日期和时间信息时,通常使用类 datedatetime 和/或 timedatetime 包裹。Babel在其 dates 模块:

>>> from datetime import date, datetime, time
>>> from babel.dates import format_date, format_datetime, format_time

>>> d = date(2007, 4, 1)
>>> format_date(d, locale='en')
u'Apr 1, 2007'
>>> format_date(d, locale='de_DE')
u'01.04.2007'

如本例所示,Babel将自动选择适合所请求区域设置的日期格式。

这个 format_*() 函数还接受可选的 format 参数,该参数允许您在四种格式变体中选择一种:

  • short

  • medium (违约),

  • long

  • full .

例如:

>>> format_date(d, format='short', locale='en')
u'4/1/07'
>>> format_date(d, format='long', locale='en')
u'April 1, 2007'
>>> format_date(d, format='full', locale='en')
u'Sunday, April 1, 2007'

核心时间概念

处理日期和时间可能是一件复杂的事情。巴别塔试图通过为你做一些决定来简化与他们的合作。Python的DateTime模块有不同的方法来处理时间和日期:朴素的和支持时区的DateTime对象。

Babel通常建议您将所有时间存储在朴素的DateTime对象中,并始终将其视为UTC。这大大简化了时间的处理,因为否则您可能会遇到处理不同时区的DateTime对象的麻烦情况。这很棘手,因为在某些情况下,时间可能是模棱两可的。在处理时区转换前后的日期时,通常会出现这种情况。时区转换最常见的情况是在夏令时和标准时间之间进行更改。

因此,我们建议始终在内部使用UTC,并且仅在将日期返回给用户时重新格式化为本地时间。在这一点上,通常可以建立用户选择的时区,并且Babel可以自动为您重新调整时间基准。

若要获取当前时间,请使用 now() 的方法。 datetime 对象,传递 utc 作为时区添加到它。

有关时区的更多信息,请参见 时区支持 .

模式语法

虽然Babel使得为给定的区域设置使用适当的日期/时间格式变得很简单,但是您也可以强制它使用自定义模式。请注意,与Python等效项相比,Babel使用不同的模式来指定数字和日期格式(例如 time.strftime() ),它们大多继承自C和POSIX。巴别塔中使用的模式基于 Locale Data Markup Language specification (LDML),其定义如下:

日期/时间模式是字符串,其中特定字符串在格式化时替换为日历中的日期和时间数据,或用于在解析时生成日历数据。 […]

字符可以多次使用。例如,如果 y 在这一年里使用, yy 可能会产生“99”,而 yyyy 制作了“1999”。对于大多数数值字段,字符数指定字段宽度。例如,如果 h 是时候了, h 可能会产生“5”,但是 hh 生成“05”。对于某些字符,计数指定应使用缩写形式还是完整形式 […]

两个单引号表示字面上的单引号,无论是在单引号内还是在单引号外。单引号内的文本不会以任何方式解释(两个相邻的单引号除外)。

例如:

>>> d = date(2007, 4, 1)
>>> format_date(d, "EEE, MMM d, ''yy", locale='en')
u"Sun, Apr 1, '07"
>>> format_date(d, "EEEE, d.M.yyyy", locale='de')
u'Sonntag, 1.4.2007'

>>> t = time(15, 30)
>>> format_time(t, "hh 'o''clock' a", locale='en')
u"03 o'clock PM"
>>> format_time(t, 'H:mm a', locale='de')
u'15:30 nachm.'

>>> dt = datetime(2007, 4, 1, 15, 30)
>>> format_datetime(dt, "yyyyy.MMMM.dd GGG hh:mm a", locale='en')
u'02007.April.01 AD 03:30 PM'

自定义日期时间格式模式的语法在 Locale Data Markup Language specification 。下表只是相对简要的概述。

日期字段

符号

描述

时代

G

替换为当前日期的纪元字符串。缩写为一至三个字母,长式为四个字母,窄式为五个字母

y

取而代之的是年份。通常,长度指定填充,但对于两个字母,它还指定最大长度。

Y

等同于 y 但使用ISO年-周日历。ISO年-完成一年的最后一周后的周增量。因此,它可能会在几天前或几天后发生变化。 y 。建议与 w 符号。

u

??

季度

Q

用1或2表示数字季度,用3表示缩写,或用4表示全名。

q

用1或2表示数字季度,用3表示缩写,或用4表示全名。

月份

M

使用1或2作为数字月份,使用3作为缩写,或使用4作为全名,或使用5作为狭义名称。

L

使用1或2作为数字月份,使用3作为缩写,或使用4作为全名,或使用5作为狭义名称。

星期

w

根据ISO年-周日历,一年中的哪一周。根据年份的不同,这可能有52或53周的时间。建议与 Y 符号。

W

每月的星期。

d

每月的哪一天。

D

一年中的哪一天。

F

每月的星期几。

g

??

一周中的某一天

E

一周中的哪一天。用1到3个字母表示短日期,或用4个字母表示全名,或用5个字母表示狭义名称。

e

当地一周中的哪一天。与E相同,不同之处在于使用一个或两个字母添加一个数字值,该值将取决于一周的本地开始日期。

c

??

时间字段

符号

描述

期间

a

上午或下午

小时

h

小时 [1-12] .

H

小时 [0-23] .

K

小时 [0-11] .

k

小时 [1-24] .

分钟

m

使用一个或两个作为零位填充。

第二

s

使用一个或两个作为零位填充。

S

小数秒,四舍五入为字母计数。

A

以天为单位的毫秒数。

时区

z

短时区使用一到三个字母,全名使用四个字母。

Z

RFC 822使用一到三个字母,GMT格式使用四个字母。

v

用一个字母表示短墙(通用)时间,用四个字母表示长墙时间。

V

等同于 z ,但应使用时区缩写,而不管它们是否为区域设置常用的缩写。

时间增量格式设置

除了提供用于格式化本地化日期和时间的函数外, babel.dates 模块还提供了格式化两个时间之间的差值的函数,称为“时间增量”。这些通常表示为 datetime.timedelta 对象,这也是减去一个 datetime 对象来自另一个对象。

这个 format_timedelta 函数使用一个 timedelta 对象,并返回人类可读的表示形式。这是以精度为代价的,因为它只选择差异中最重要的单位(如年、周或小时),并显示:

>>> from datetime import timedelta
>>> from babel.dates import format_timedelta
>>> delta = timedelta(days=6)
>>> format_timedelta(delta, locale='en_US')
u'1 week'

结果字符串基于CLDR数据,并根据区域设置的复数规则和计算的单位数进行适当的复数。

该函数为您提供参数,以影响如何选择此最重要的单位: threshold 设置值后,演示文稿将切换到下一个更大的单位,并使用 granularity 您可以限制要显示的最小单位:

>>> delta = timedelta(days=6)
>>> format_timedelta(delta, threshold=1.2, locale='en_US')
u'6 days'
>>> format_timedelta(delta, granularity='month', locale='en_US')
u'1 month'

时区支持

许多详细时间格式都包括时区,但默认情况下,时区信息不适用于Python datetimetime 对象。标准库仅包括摘要 tzinfo 类,您需要相应的实现才能在应用程序中实际使用。巴别塔包括一个 tzinfo 实施UTC(世界时)。

巴别塔使用的是 `zoneinfo`_pytz 以获得时区支持。如果安装了pytz,那么它将优先于标准库的zoneinfo。您可以从Babel中直接与这些模块中的任何一个进行交互:

>>> from datetime import time
>>> from babel.dates import get_timezone, UTC
>>> dt = datetime(2007, 4, 1, 15, 30, tzinfo=UTC)
>>> eastern = get_timezone('US/Eastern')
>>> format_datetime(dt, 'H:mm Z', tzinfo=eastern, locale='en_US')
u'11:30 -0400'

在Python应用程序中处理不同时区的推荐方法是始终在内部使用UTC,并且仅在接受用户输入和显示日期/时间数据时分别从用户时区转换为用户时区。你可以和巴别塔一起使用 zoneinfopytz 要将时区应用于任何 datetimetime 对象用于显示,保持原始信息不变:

>>> british = get_timezone('Europe/London')
>>> format_datetime(dt, 'H:mm zzzz', tzinfo=british, locale='en_US')
u'16:30 British Summer Time'

这里,给定的UTC时间调整为“欧洲/伦敦”时区,并考虑夏令时。夏令时也适用于 format_time ,但是因为在这种情况下实际日期是未知的,所以假定是当天来确定应该使用DST还是标准时间。

Babel还支持使用操作系统的本地时区。它是通过 LOCALTZ 常量:

>>> from babel.dates import LOCALTZ, get_timezone_name
>>> LOCALTZ
<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>
>>> get_timezone_name(LOCALTZ)
u'Central European Time'

本地化时区名称

Locale 类提供对与时区相关的各种区域设置显示名称的访问,但是构建时区的本地化名称的过程实际上相当复杂。Babel在 babel.dates 模块,最重要的是 get_timezone_name 功能:

>>> from babel import Locale
>>> from babel.dates import get_timezone_name, get_timezone

>>> tz = get_timezone('Europe/Berlin')
>>> get_timezone_name(tz, locale=Locale.parse('pt_PT'))
u'Hora da Europa Central'

您可以将该函数传递给 datetime.tzinfo 对象,或 datetime.datedatetime.datetime 对象。如果您传递的是实际日期,该函数将能够将夏令时考虑在内。如果只传递时区,则Babel不知道夏令时是否有效,因此它使用通用表示法,例如向用户显示时区列表时很有用。

>>> from datetime import datetime
>>> from babel.dates import _localize

>>> dt = _localize(tz, datetime(2007, 8, 15))
>>> get_timezone_name(dt, locale=Locale.parse('de_DE'))
u'Mitteleurop\xe4ische Sommerzeit'
>>> get_timezone_name(tz, locale=Locale.parse('de_DE'))
u'Mitteleurop\xe4ische Zeit'