日期和时间¶
在Python中使用日期和时间信息时,通常使用类 date
, datetime
和/或 time
从 datetime 包裹。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 datetime
和 time
对象。标准库仅包括摘要 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,并且仅在接受用户输入和显示日期/时间数据时分别从用户时区转换为用户时区。你可以和巴别塔一起使用 zoneinfo
或 pytz
要将时区应用于任何 datetime
或 time
对象用于显示,保持原始信息不变:
>>> 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.date
或 datetime.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'