8.1. datetime — 基本日期和时间类型 — Python 文档
8.1. 约会时间 — 基本日期和时间类型
2.3 版中的新功能。
datetime 模块提供了以简单和复杂方式操作日期和时间的类。 虽然支持日期和时间算术,但实现的重点是高效的属性提取以进行输出格式化和操作。 有关相关功能,另请参阅 time 和 calendar 模块。
有两种日期和时间对象:“naive”和“aware”。
感知对象具有足够的适用算法和政治时间调整知识,例如时区和夏令时信息,以相对于其他感知对象定位自身。 一个有意识的对象被用来表示一个特定的时刻,它是不可解释的 1。
一个天真的对象不包含足够的信息来明确地相对于其他日期/时间对象定位自己。 一个简单的对象是否代表协调世界时 (UTC)、本地时间或其他时区的时间完全取决于程序,就像特定数字代表米、英里或质量取决于程序一样。 朴素的对象易于理解和使用,但代价是忽略了现实的某些方面。
对于需要感知对象的应用程序,datetime 和 time 对象有一个可选的时区信息属性,tzinfo
,可以设置为抽象子类的实例tzinfo 类。 这些 tzinfo 对象捕获有关 UTC 时间偏移量、时区名称以及夏令时是否生效的信息。 请注意,datetime 模块没有提供具体的 tzinfo 类。 支持任何需要的详细级别的时区取决于应用程序。 世界各地的时间调整规则政治性多于理性,没有适用于所有应用的标准。
datetime 模块导出以下常量:
8.1.1. 可用类型
这些类型的对象是不可变的。
date 类型的对象总是简单的。
time 或 datetime 类型的对象可能是幼稚的或有意识的。 datetime 对象 d 知道 d.tzinfo
不是 None
并且 d.tzinfo.utcoffset(d)
不返回 None
。 如果 d.tzinfo
是 None
,或者如果 d.tzinfo
不是 None
但 d.tzinfo.utcoffset(d)
返回 None
,d 天真。 time 对象 t 知道 t.tzinfo
不是 None
并且 t.tzinfo.utcoffset(None)
不返回 None
。 否则, t 是幼稚的。
naive 和aware 之间的区别不适用于 timedelta 对象。
子类关系:
object
timedelta
tzinfo
time
date
datetime
8.1.2. 时间增量对象
timedelta 对象表示持续时间,即两个日期或时间之间的差异。
- class datetime.timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
所有参数都是可选的,默认为
0
。 参数可以是整数、长整数或浮点数,也可以是正数或负数。只有天、秒和微秒在内部存储。 参数被转换为这些单位:
一毫秒转换为 1000 微秒。
一分钟转换为 60 秒。
一小时转换为 3600 秒。
一周转换为 7 天。
然后将天、秒和微秒归一化,以便表示是唯一的,其中
0 <= microseconds < 1000000
0 <= seconds < 3600*24
(一天的秒数)-999999999 <= days <= 999999999
如果任何参数是浮点数并且存在小数微秒,则将从所有参数剩余的小数微秒组合起来,并将它们的总和四舍五入到最接近的微秒。 如果没有参数是浮点数,则转换和规范化过程是精确的(没有信息丢失)。
如果天数的归一化值超出指定范围,则提高
OverflowError
。请注意,负值的归一化起初可能会令人惊讶。 例如,
>>> from datetime import timedelta >>> d = timedelta(microseconds=-1) >>> (d.days, d.seconds, d.microseconds) (-1, 86399, 999999)
类属性是:
- timedelta.min
- 最负的 timedelta 对象,
timedelta(-999999999)
。
- timedelta.max
- 最正的 timedelta 对象,
timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999)
。
- timedelta.resolution
- 不相等的 timedelta 对象之间的最小可能差异,
timedelta(microseconds=1)
。
请注意,由于标准化,timedelta.max
> -timedelta.min
。 -timedelta.max
不能表示为 timedelta 对象。
实例属性(只读):
属性 | 价值 |
---|---|
days
|
-999999999 和 999999999 之间(含) |
seconds
|
0 到 86399 之间(含) |
microseconds
|
0 到 999999 之间(含) |
支持的操作:
操作 | 结果 |
---|---|
t1 = t2 + t3
|
t2 和 t3 的总和。 之后 t1-t2 == t3 和 t1-t3 == t2是真的。 (1) |
t1 = t2 - t3
|
t2和t3的区别。 之后 t1 == t2 - t3 和 t2 == t1 + t3是真的。 (1) |
t1 = t2 * i or t1 = i * t2
|
Delta 乘以整数或长整数。 之后 t1 // i == t2 为真,前提是 i != 0 。
|
一般来说,t1 * i == t1 * (i-1) + t1 是真的。 (1) | |
t1 = t2 // i
|
计算地板并丢弃剩余部分(如果有)。 (3) |
+t1
|
返回具有相同值的 timedelta 对象。 (2) |
-t1
|
相当于 timedelta(-t1.days, -t1.seconds, -t1.microseconds),和 t1 * -1。 (1)(4) |
abs(t)
|
t.days >= 0 时相当于 +t,t.days < 0 时相当于 -t。 (2)
|
str(t)
|
以 [D day[s], ][H]H:MM:SS[.UUUUUU] 形式返回字符串,其中 D 为负数表示负数 t 。 (5)
|
repr(t)
|
以 datetime.timedelta(D[, S[, U]]) 形式返回字符串,其中 D 为负数表示负数 t 。 (5)
|
注意事项:
这是准确的,但可能会溢出。
这是准确的,不能溢出。
除以 0 会增加
ZeroDivisionError
。-timedelta.max 不能表示为 timedelta 对象。
timedelta 对象的字符串表示与它们的内部表示类似地标准化。 这导致负时间增量的一些不寻常的结果。 例如:
>>> timedelta(hours=-5) datetime.timedelta(-1, 68400) >>> print(_) -1 day, 19:00:00
除了上面列出的操作 timedelta 对象支持某些与 date 和 datetime 对象的加法和减法(见下文)。
支持 timedelta 对象与 timedelta 对象的比较,表示较小的持续时间被认为是较小的 timedelta。 为了阻止混合类型比较回退到对象地址的默认比较,当 timedelta 对象与不同类型的对象进行比较时,除非比较,否则会引发 TypeError
是 ==
或 !=
。 后一种情况分别返回 False 或 True。
timedelta 对象是 hashable(可用作字典键),支持高效酸洗,并且在布尔上下文中,timedelta 对象被认为是真当且仅当它不等于 timedelta(0)
。
实例方法:
- timedelta.total_seconds()
返回持续时间中包含的总秒数。 相当于在启用真除法的情况下计算的
(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
。请注意,对于非常大的时间间隔(在大多数平台上超过 270 年),此方法将失去微秒精度。
2.7 版中的新功能。
用法示例:
>>> from datetime import timedelta
>>> year = timedelta(days=365)
>>> another_year = timedelta(weeks=40, days=84, hours=23,
... minutes=50, seconds=600) # adds up to 365 days
>>> year.total_seconds()
31536000.0
>>> year == another_year
True
>>> ten_years = 10 * year
>>> ten_years, ten_years.days // 365
(datetime.timedelta(3650), 10)
>>> nine_years = ten_years - year
>>> nine_years, nine_years.days // 365
(datetime.timedelta(3285), 9)
>>> three_years = nine_years // 3;
>>> three_years, three_years.days // 365
(datetime.timedelta(1095), 3)
>>> abs(three_years - ten_years) == 2 * three_years + year
True
8.1.3. 日期对象
date 对象表示理想化日历中的日期(年、月和日),当前的公历在两个方向上无限延伸。 第 1 年的 1 月 1 日称为第 1 天,第 1 年的 1 月 2 日称为第 2 天,依此类推。 这与 Dershowitz 和 Reingold 的著作 Calendrical Calculations 中的“proleptic Gregorian”日历的定义相匹配,它是所有计算的基准日历。 有关在预测公历序数和许多其他日历系统之间转换的算法,请参阅本书。
- class datetime.date(year, month, day)
所有参数都是必需的。 参数可以是整数或长整数,范围如下:
MINYEAR <= year <= MAXYEAR
1 <= month <= 12
1 <= day <= number of days in the given month and year
如果给出了超出这些范围的参数,则会引发
ValueError
。
其他构造函数,所有类方法:
- classmethod date.today()
- 返回当前本地日期。 这相当于
date.fromtimestamp(time.time())
。
- classmethod date.fromtimestamp(timestamp)
- 返回POSIX时间戳对应的本地日期,如time.time()返回。 如果时间戳超出平台 C
localtime()
函数支持的值范围,这可能会引发ValueError
。 这通常被限制在 1970 年到 2038 年之间。 请注意,在时间戳概念中包含闰秒的非 POSIX 系统上,fromtimestamp() 会忽略闰秒。
- classmethod date.fromordinal(ordinal)
- 返回对应于预测格列高利序数的日期,其中第 1 年的 1 月 1 日的序数为 1。
ValueError
升高,除非1 <= ordinal <= date.max.toordinal()
。 对于任何日期 d、date.fromordinal(d.toordinal()) == d
。
类属性:
- date.min
- 最早可表示的日期,
date(MINYEAR, 1, 1)
。
- date.max
- 可表示的最晚日期,
date(MAXYEAR, 12, 31)
。
- date.resolution
- 不等日期对象之间的最小可能差异,
timedelta(days=1)
。
实例属性(只读):
- date.month
- 1 到 12 之间(含)。
- date.day
- 介于 1 和给定年份的给定月份中的天数之间。
支持的操作:
操作 | 结果 |
---|---|
date2 = date1 + timedelta
|
date2 是从 date1 移除的 timedelta.days 天。 (1)
|
date2 = date1 - timedelta
|
计算 date2 使得 date2 + timedelta == date1 。 (2)
|
timedelta = date1 - date2
|
(3) |
date1 < date2
|
当 date1 在时间上先于 date2 时,date1 被认为小于 date2。 (4) |
注意事项:
- 如果
timedelta.days > 0
,则 date2 在时间上向前移动,如果timedelta.days < 0
,则向后移动。 之后date2 - date1 == timedelta.days
。timedelta.seconds
和timedelta.microseconds
被忽略。 如果date2.year
小于 MINYEAR 或大于 MAXYEAR,则会引发OverflowError
。 - 这并不完全等同于 date1 + (-timedelta),因为在 date1 - timedelta 没有的情况下,隔离的 -timedelta 可能会溢出。
timedelta.seconds
和timedelta.microseconds
被忽略。 - 这是准确的,不能溢出。 timedelta.seconds 和 timedelta.microseconds 为 0,并且 date2 + timedelta == date1 之后。
- 换句话说,
date1 < date2
当且仅当date1.toordinal() < date2.toordinal()
。 为了阻止比较返回到比较对象地址的默认方案,如果另一个比较对象不是 date 对象,则日期比较通常会引发TypeError
。 但是,如果另一个比较对象具有timetuple()
属性,则会返回NotImplemented
。 这个钩子为其他类型的日期对象提供了实现混合类型比较的机会。 如果不是,当 date 对象与不同类型的对象进行比较时,除非比较是==
或!=
,否则会引发TypeError
。 后一种情况分别返回 False 或 True。
日期可以用作字典键。 在布尔上下文中,所有 date 对象都被认为是 true。
实例方法:
- date.replace(year, month, day)
- 返回具有相同值的日期,除了那些由指定的关键字参数赋予新值的参数。 例如,如果
d == date(2002, 12, 31)
,则d.replace(day=26) == date(2002, 12, 26)
。
- date.timetuple()
- 返回一个 time.struct_time,例如由 time.localtime() 返回。 小时、分钟和秒为 0,DST 标志为 -1。
d.timetuple()
等价于time.struct_time((d.year, d.month, d.day, 0, 0, 0, d.weekday(), yday, -1))
,其中yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1
是当前年份中的天数,从1
开始,表示 1 月 1 日。
- date.toordinal()
- 返回日期的预测格列高利序数,其中第 1 年的 1 月 1 日的序数为 1。 对于任何 date 对象 d、
date.fromordinal(d.toordinal()) == d
。
- date.weekday()
- 以整数形式返回星期几,其中星期一为 0,星期日为 6。 例如,
date(2002, 12, 4).weekday() == 2
,星期三。 另见 isoweekday()。
- date.isoweekday()
- 以整数形式返回星期几,其中星期一为 1,星期日为 7。 例如,
date(2002, 12, 4).isoweekday() == 3
,星期三。 另见 weekday()、isocalendar()。
- date.isocalendar()
返回一个 3 元组,(ISO 年份、ISO 周数、ISO 工作日)。
ISO 日历是一种广泛使用的公历变体。 请参阅 https://www.staff.science.uu.nl/~gent0113/calendar/isocalendar.htm 以获得很好的解释。
ISO 年由 52 或 53 个整周组成,其中一周从星期一开始到星期日结束。 ISO 年的第一周是包含星期四的一年中的第一个(公历)日历周。 这称为第 1 周,该星期四的 ISO 年份与其格里高利年相同。
例如,2004 从星期四开始,因此 ISO 2004 年的第一周从 2003 年 12 月 29 日星期一开始,到 2004 年 1 月 4 日星期日结束,因此
date(2003, 12, 29).isocalendar() == (2004, 1, 1)
和date(2004, 1, 4).isocalendar() == (2004, 1, 7)
。
- date.isoformat()
- 以 ISO 8601 格式返回一个表示日期的字符串,'YYYY-MM-DD'。 例如,
date(2002, 12, 4).isoformat() == '2002-12-04'
。
- date.__str__()
- 对于日期 d,
str(d)
等价于d.isoformat()
。
- date.ctime()
- 返回表示日期的字符串,例如
date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'
。d.ctime()
等价于time.ctime(time.mktime(d.timetuple()))
在原生 Cctime()
函数(time.ctime() 调用,但 date)的平台上。 ctime() 不调用) 符合 C 标准。
- date.strftime(format)
- 返回一个表示日期的字符串,由显式格式字符串控制。 参考小时、分钟或秒的格式代码将看到 0 值。 有关格式化指令的完整列表,请参阅 strftime() 和 strptime() 行为 部分。
- date.__format__(format)
- 与 date.strftime() 相同。 这使得在使用 str.format() 时可以为 date 对象指定格式字符串。 请参阅部分 strftime() 和 strptime() 行为 。
计算事件天数的示例:
>>> import time
>>> from datetime import date
>>> today = date.today()
>>> today
datetime.date(2007, 12, 5)
>>> today == date.fromtimestamp(time.time())
True
>>> my_birthday = date(today.year, 6, 24)
>>> if my_birthday < today:
... my_birthday = my_birthday.replace(year=today.year + 1)
>>> my_birthday
datetime.date(2008, 6, 24)
>>> time_to_birthday = abs(my_birthday - today)
>>> time_to_birthday.days
202
使用 date 的示例:
>>> from datetime import date
>>> d = date.fromordinal(730920) # 730920th day after 1. 1. 0001
>>> d
datetime.date(2002, 3, 11)
>>> t = d.timetuple()
>>> for i in t:
... print i
2002 # year
3 # month
11 # day
0
0
0
0 # weekday (0 = Monday)
70 # 70th day in the year
-1
>>> ic = d.isocalendar()
>>> for i in ic:
... print i
2002 # ISO year
11 # ISO week number
1 # ISO day number ( 1 = Monday )
>>> d.isoformat()
'2002-03-11'
>>> d.strftime("%d/%m/%y")
'11/03/02'
>>> d.strftime("%A %d. %B %Y")
'Monday 11. March 2002'
>>> 'The {1} is {0:%d}, the {2} is {0:%B}.'.format(d, "day", "month")
'The day is 11, the month is March.'
8.1.4. 约会时间对象
datetime 对象是包含来自 date 对象和 time 对象的所有信息的单个对象。 与 date 对象一样,datetime 假定当前的公历向两个方向扩展; 就像一个时间对象,datetime 假设每天正好有 3600*24 秒。
构造函数:
- class datetime.datetime(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])
年、月和日参数是必需的。 tzinfo 可以是
None
,或 tzinfo 子类的实例。 其余参数可以是整数或长整数,范围如下:MINYEAR <= year <= MAXYEAR
1 <= month <= 12
1 <= day <= number of days in the given month and year
0 <= hour < 24
0 <= minute < 60
0 <= second < 60
0 <= microsecond < 1000000
如果给出了超出这些范围的参数,则会引发
ValueError
。
其他构造函数,所有类方法:
- classmethod datetime.today()
- 返回当前本地日期时间,使用 tzinfo
None
。 这相当于datetime.fromtimestamp(time.time())
。 另见 now()、fromtimestamp()。
- classmethod datetime.now([tz])
返回当前本地日期和时间。 如果可选参数 tz 是
None
或未指定,则类似于 today(),但是,如果可能,提供比通过通过time.time() 时间戳(例如,这可能在提供 Cgettimeofday()
函数的平台上是可能的)。如果 tz 不是
None
,则必须是 tzinfo 子类的实例,并将当前日期和时间转换为 tz' s 时区。 在这种情况下,结果等同于tz.fromutc(datetime.utcnow().replace(tzinfo=tz))
。 另见 today()、utcnow()。
- classmethod datetime.utcnow()
- 返回当前 UTC 日期和时间,使用 tzinfo
None
。 这类似于 now(),但返回当前 UTC 日期和时间,作为一个简单的 datetime 对象。 另见 now()。
- classmethod datetime.fromtimestamp(timestamp[, tz])
返回POSIX时间戳对应的本地日期时间,如time.time()返回。 如果可选参数 tz 为
None
或未指定,则时间戳将转换为平台的本地日期和时间,并且返回的 datetime 对象是朴素的。如果tz不是
None
,则必须是tzinfo子类的实例,时间戳转换为tz的时区. 在这种情况下,结果等同于tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))
。fromtimestamp() 可能会引发
ValueError
,如果时间戳超出平台 Clocaltime()
或gmtime()
函数支持的值范围。 这通常被限制在 1970 年到 2038 年之间。 请注意,在时间戳概念中包含闰秒的非 POSIX 系统上,fromtimestamp() 会忽略闰秒,然后可能有两个相差一秒的时间戳产生相同的 ]datetime 对象。 另见 utcfromtimestamp()。
- classmethod datetime.utcfromtimestamp(timestamp)
- 返回 POSIX 时间戳对应的 UTC datetime,带有 tzinfo
None
。 如果时间戳超出平台 Cgmtime()
函数支持的值范围,这可能会引发ValueError
。 这通常被限制在 1970 年到 2038 年之间。 另见 fromtimestamp()。
- classmethod datetime.fromordinal(ordinal)
- 返回对应于预测格列高利序数的 datetime,其中第 1 年的 1 月 1 日的序数为 1。
ValueError
升高,除非1 <= ordinal <= datetime.max.toordinal()
。 结果的时分秒微秒均为0,tzinfo为None
。
- classmethod datetime.combine(date, time)
- 返回一个新的 datetime 对象,其日期分量等于给定的 date 对象,并且其时间分量和 tzinfo 属性等于给定的 time 对象的。 对于任何 datetime 对象 d、
d == datetime.combine(d.date(), d.timetz())
。 如果 date 是 datetime 对象,则忽略其时间分量和 tzinfo 属性。
- classmethod datetime.strptime(date_string, format)
返回date_string对应的datetime,按照格式解析。 这相当于
datetime(*(time.strptime(date_string, format)[0:6]))
。ValueError
。 有关格式化指令的完整列表,请参阅 strftime() 和 strptime() 行为 部分。2.5 版中的新功能。
类属性:
- datetime.min
- 最早可表示的datetime、
datetime(MINYEAR, 1, 1, tzinfo=None)
。
- datetime.max
- 最新可表示的 datetime、
datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, tzinfo=None)
。
- datetime.resolution
- 不相等的 datetime 对象之间的最小可能差异,
timedelta(microseconds=1)
。
实例属性(只读):
- datetime.month
- 1 到 12 之间(含)。
- datetime.day
- 介于 1 和给定年份的给定月份中的天数之间。
- datetime.hour
- 在
range(24)
中。
- datetime.minute
- 在
range(60)
中。
- datetime.second
- 在
range(60)
中。
- datetime.microsecond
- 在
range(1000000)
中。
- datetime.tzinfo
- 对象作为 tzinfo 参数传递给 datetime 构造函数,或者
None
如果没有传递。
支持的操作:
操作 | 结果 |
---|---|
datetime2 = datetime1 + timedelta
|
(1) |
datetime2 = datetime1 - timedelta
|
(2) |
timedelta = datetime1 - datetime2
|
(3) |
datetime1 < datetime2
|
将 datetime 与 datetime 进行比较。 (4) |
datetime2 是从 datetime1 中删除的 timedelta 的持续时间,如果
timedelta.days
> 0,或向后,如果timedelta.days
< 0。 结果具有与输入日期时间相同的 tzinfo 属性,之后的 datetime2 - datetime1 == timedelta。 如果 datetime2.year 小于 MINYEAR 或大于 MAXYEAR,则会引发OverflowError
。 请注意,即使输入是感知对象,也不会进行时区调整。计算 datetime2 使得 datetime2 + timedelta == datetime1。 至于加法,结果与输入日期时间具有相同的 tzinfo 属性,即使输入知道也不会进行时区调整。 这并不完全等同于 datetime1 + (-timedelta),因为在 datetime1 - timedelta 没有的情况下,隔离的 -timedelta 可能会溢出。
从 datetime 减去 datetime 仅在两个操作数都是朴素的或两者都知道时才定义。 如果一个人知道而另一个人天真,则提出
TypeError
。如果两者都是幼稚的,或者两者都知道并且具有相同的 tzinfo 属性,则忽略 tzinfo 属性,结果是一个 timedelta 对象 t 使得
datetime2 + t == datetime1
。 在这种情况下不进行时区调整。如果两者都知道并且具有不同的 tzinfo 属性,则
a-b
的行为就像首先将 a 和 b 首先转换为朴素的 UTC 日期时间一样。 结果是(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset())
,只是实现永远不会溢出。当 datetime1 在时间上先于 datetime2 时,datetime1 被认为小于 datetime2。
如果一个比较是天真的而另一个知道,则
TypeError
被提高。 如果两个比较数都知道,并且具有相同的 tzinfo 属性,则公共 tzinfo 属性将被忽略并比较基准日期时间。 如果两个比较数都知道并且具有不同的 tzinfo 属性,则首先通过减去它们的 UTC 偏移量(从self.utcoffset()
获得)来调整比较数。
datetime 对象可以用作字典键。 在布尔上下文中,所有 datetime 对象都被认为是 true。
实例方法:
- datetime.date()
- 返回具有相同年月日的 date 对象。
- datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]])
- 返回具有相同属性的日期时间,除了那些由指定的关键字参数赋予新值的属性。 请注意,可以指定
tzinfo=None
以从已知日期时间创建一个简单的日期时间,而无需转换日期和时间数据。
- datetime.astimezone(tz)
返回具有新的 tzinfo 属性 tz 的 datetime 对象,调整日期和时间数据,使结果与 self 的 UTC 时间相同,但在 tz 的本地时间。
tz 必须是 tzinfo 子类的实例,其 utcoffset() 和 dst() 方法不得返回
None
。 self一定要知道(self.tzinfo
不能是None
,self.utcoffset()
不能返回None
)。如果
self.tzinfo
为tz,self.astimezone(tz)
等于self:不调整日期或时间数据。 否则结果是时区 tz 中的本地时间,表示与 self 相同的 UTC 时间:在astz = dt.astimezone(tz)
之后,astz - astz.utcoffset()
通常会有相同的日期和时间数据为dt - dt.utcoffset()
。 类 tzinfo 的讨论解释了在夏令时过渡边界无法实现的情况(仅当 tz 对标准时间和夏令时进行建模时才会出现问题)。如果您只想将时区对象 tz 附加到日期时间 dt 而不调整日期和时间数据,请使用
dt.replace(tzinfo=tz)
。 如果您只想从已知日期时间 dt 中删除时区对象而不转换日期和时间数据,请使用dt.replace(tzinfo=None)
。请注意,默认的 tzinfo.fromutc() 方法可以在 tzinfo 子类中被覆盖,以影响 astimezone() 返回的结果。 忽略错误情况,astimezone() 的作用类似于:
def astimezone(self, tz): if self.tzinfo is tz: return self # Convert self to UTC, and attach the new time zone object. utc = (self - self.utcoffset()).replace(tzinfo=tz) # Convert from UTC to tz's local time. return tz.fromutc(utc)
- datetime.utcoffset()
- 如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.utcoffset(self)
,如果后者不返回None
,则引发异常,或 timedelta 对象,表示大小小于一天的整数分钟。
- datetime.dst()
- 如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.dst(self)
,如果后者不返回None
,则引发异常,或 timedelta 对象,表示大小小于一天的整数分钟。
- datetime.tzname()
- 如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.tzname(self)
,如果后者不返回None
或一个字符串对象,
- datetime.timetuple()
- 返回一个 time.struct_time,例如由 time.localtime() 返回。
d.timetuple()
等价于time.struct_time((d.year, d.month, d.day, d.hour, d.minute, d.second, d.weekday(), yday, dst))
,其中yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1
是当前年份中的天数,从1
开始,表示 1 月 1 日。 结果的tm_isdst
标志根据dst()方法设置:tzinfo为None
或dst() ]返回None
,tm_isdst
设置为-1
; 否则如果 dst() 返回非零值,则tm_isdst
设置为1
; 否则tm_isdst
设置为0
。
- datetime.utctimetuple()
如果 datetime 实例 d 是 naive,这与
d.timetuple()
相同,除了tm_isdst
被强制为 0,而不管d.dst()
] 返回。 DST 永远不会在 UTC 时间生效。如果 d 知道,d 被归一化为 UTC 时间,通过减去
d.utcoffset()
,并返回归一化时间的 time.struct_time .tm_isdst
强制为 0。 请注意,结果的tm_year
成员可能是 MINYEAR-1 或 MAXYEAR+1,如果 d.year 是MINYEAR
或MAXYEAR
和 UTC 调整溢出一年边界。
- datetime.toordinal()
- 返回日期的预测格列高利序数。 与
self.date().toordinal()
相同。
- datetime.weekday()
- 以整数形式返回星期几,其中星期一为 0,星期日为 6。 与
self.date().weekday()
相同。 另见 isoweekday()。
- datetime.isoweekday()
- 以整数形式返回星期几,其中星期一为 1,星期日为 7。 与
self.date().isoweekday()
相同。 另见 weekday()、isocalendar()。
- datetime.isocalendar()
- 返回一个 3 元组,(ISO 年份、ISO 周数、ISO 工作日)。 与
self.date().isocalendar()
相同。
- datetime.isoformat([sep])
以 ISO 8601 格式返回表示日期和时间的字符串,YYYY-MM-DDTHH:MM:SS.mmmmmm 或者,如果 microsecond 为 0,则 YYYY-MM-DDTHH:MM:SS
如果 utcoffset() 不返回
None
,则附加一个 6 字符的字符串,以(带符号的)小时和分钟给出 UTC 偏移量:YYYY-MM-DDTHH:MM:SS。 mmmmmm+HH:MM 或者,如果 microsecond 是 0 YYYY-MM-DDTHH:MM:SS+HH:MM可选参数 sep(默认为
'T'
)是一个单字符分隔符,位于结果的日期和时间部分之间。 例如,>>> from datetime import tzinfo, timedelta, datetime >>> class TZ(tzinfo): ... def utcoffset(self, dt): return timedelta(minutes=-399) ... >>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ') '2002-12-25 00:00:00-06:39'
- datetime.__str__()
- 对于 datetime 实例 d,
str(d)
相当于d.isoformat(' ')
。
- datetime.ctime()
- 返回表示日期和时间的字符串,例如
datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'
。d.ctime()
在本机 Cctime()
函数(time.ctime() 调用,但 datetime. ctime() 不调用) 符合 C 标准。
- datetime.strftime(format)
- 返回一个表示日期和时间的字符串,由显式格式字符串控制。 有关格式化指令的完整列表,请参阅 strftime() 和 strptime() 行为 部分。
- datetime.__format__(format)
- 与 datetime.strftime() 相同。 这使得在使用 str.format() 时为 datetime 对象指定格式字符串成为可能。 请参阅部分 strftime() 和 strptime() 行为 。
使用日期时间对象的示例:
>>> from datetime import datetime, date, time
>>> # Using datetime.combine()
>>> d = date(2005, 7, 14)
>>> t = time(12, 30)
>>> datetime.combine(d, t)
datetime.datetime(2005, 7, 14, 12, 30)
>>> # Using datetime.now() or datetime.utcnow()
>>> datetime.now()
datetime.datetime(2007, 12, 6, 16, 29, 43, 79043) # GMT +1
>>> datetime.utcnow()
datetime.datetime(2007, 12, 6, 15, 29, 43, 79060)
>>> # Using datetime.strptime()
>>> dt = datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M")
>>> dt
datetime.datetime(2006, 11, 21, 16, 30)
>>> # Using datetime.timetuple() to get tuple of all attributes
>>> tt = dt.timetuple()
>>> for it in tt:
... print it
...
2006 # year
11 # month
21 # day
16 # hour
30 # minute
0 # second
1 # weekday (0 = Monday)
325 # number of days since 1st January
-1 # dst - method tzinfo.dst() returned None
>>> # Date in ISO format
>>> ic = dt.isocalendar()
>>> for it in ic:
... print it
...
2006 # ISO year
47 # ISO week
2 # ISO weekday
>>> # Formatting datetime
>>> dt.strftime("%A, %d. %B %Y %I:%M%p")
'Tuesday, 21. November 2006 04:30PM'
>>> 'The {1} is {0:%d}, the {2} is {0:%B}, the {3} is {0:%I:%M%p}.'.format(dt, "day", "month", "time")
'The day is 21, the month is November, the time is 04:30PM.'
将日期时间与 tzinfo 一起使用:
>>> from datetime import timedelta, datetime, tzinfo
>>> class GMT1(tzinfo):
... def utcoffset(self, dt):
... return timedelta(hours=1) + self.dst(dt)
... def dst(self, dt):
... # DST starts last Sunday in March
... d = datetime(dt.year, 4, 1) # ends last Sunday in October
... self.dston = d - timedelta(days=d.weekday() + 1)
... d = datetime(dt.year, 11, 1)
... self.dstoff = d - timedelta(days=d.weekday() + 1)
... if self.dston <= dt.replace(tzinfo=None) < self.dstoff:
... return timedelta(hours=1)
... else:
... return timedelta(0)
... def tzname(self,dt):
... return "GMT +1"
...
>>> class GMT2(tzinfo):
... def utcoffset(self, dt):
... return timedelta(hours=2) + self.dst(dt)
... def dst(self, dt):
... d = datetime(dt.year, 4, 1)
... self.dston = d - timedelta(days=d.weekday() + 1)
... d = datetime(dt.year, 11, 1)
... self.dstoff = d - timedelta(days=d.weekday() + 1)
... if self.dston <= dt.replace(tzinfo=None) < self.dstoff:
... return timedelta(hours=1)
... else:
... return timedelta(0)
... def tzname(self,dt):
... return "GMT +2"
...
>>> gmt1 = GMT1()
>>> # Daylight Saving Time
>>> dt1 = datetime(2006, 11, 21, 16, 30, tzinfo=gmt1)
>>> dt1.dst()
datetime.timedelta(0)
>>> dt1.utcoffset()
datetime.timedelta(0, 3600)
>>> dt2 = datetime(2006, 6, 14, 13, 0, tzinfo=gmt1)
>>> dt2.dst()
datetime.timedelta(0, 3600)
>>> dt2.utcoffset()
datetime.timedelta(0, 7200)
>>> # Convert datetime to another time zone
>>> dt3 = dt2.astimezone(GMT2())
>>> dt3
datetime.datetime(2006, 6, 14, 14, 0, tzinfo=<GMT2 object at 0x...>)
>>> dt2
datetime.datetime(2006, 6, 14, 13, 0, tzinfo=<GMT1 object at 0x...>)
>>> dt2.utctimetuple() == dt3.utctimetuple()
True
8.1.5. 时间对象
时间对象表示一天中的(本地)时间,独立于任何特定的一天,并且可以通过 tzinfo 对象进行调整。
- class datetime.time([hour[, minute[, second[, microsecond[, tzinfo]]]]])
所有参数都是可选的。 tzinfo 可以是
None
,或 tzinfo 子类的实例。 其余参数可以是整数或长整数,范围如下:0 <= hour < 24
0 <= minute < 60
0 <= second < 60
0 <= microsecond < 1000000
。
如果给出了超出这些范围的参数,则会引发
ValueError
。 所有默认为0
,除了 tzinfo,默认为 None。
类属性:
- time.min
- 最早可表示的时间、
time(0, 0, 0, 0)
。
- time.max
- 最新可表示的 time、
time(23, 59, 59, 999999)
。
实例属性(只读):
- time.hour
- 在
range(24)
中。
- time.minute
- 在
range(60)
中。
- time.second
- 在
range(60)
中。
- time.microsecond
- 在
range(1000000)
中。
- time.tzinfo
- 该对象作为 tzinfo 参数传递给 time 构造函数,或者
None
如果没有传递。
支持的操作:
- time 与 time 的比较,其中当 a 在 b 之前时,认为 a 小于 b' 及时。 如果一个比较是天真的而另一个知道,则
TypeError
被提高。 如果两个比较数都知道,并且具有相同的 tzinfo 属性,则忽略公共的 tzinfo 属性并比较基准时间。 如果两个比较数都知道并且具有不同的 tzinfo 属性,则首先通过减去它们的 UTC 偏移量(从self.utcoffset()
获得)来调整比较数。 为了阻止混合类型比较回退到对象地址的默认比较,当 time 对象与不同类型的对象进行比较时,除非比较,否则会引发TypeError
是==
或!=
。 后一种情况分别返回 False 或 True。 - 哈希,用作字典键
- 高效酸洗
- 在布尔上下文中,当且仅当将 time 对象转换为分钟并减去
utcoffset()
(或0
,如果是 [ X170X]),结果非零。
实例方法:
- time.replace([hour[, minute[, second[, microsecond[, tzinfo]]]]])
- 返回具有相同值的 time,除了那些由指定的关键字参数赋予新值的属性。 请注意,可以指定
tzinfo=None
以从感知 time 创建一个朴素的 time,而无需转换时间数据。
- time.isoformat()
- 以 ISO 8601 格式返回表示时间的字符串,HH:MM:SS.mmmmmm 或者,如果 self.microsecond 为 0,则 HH:MM:SS 如果 utcoffset() 不返回
None
],附加一个 6 个字符的字符串,以(带符号的)小时和分钟给出 UTC 偏移量:HH:MM:SS.mmmmmm+HH:MM 或者,如果 self.microsecond 为 0,则 HH:MM:SS+HH:毫米
- time.__str__()
- 对于时间 t,
str(t)
等价于t.isoformat()
。
- time.strftime(format)
- 返回一个表示时间的字符串,由显式格式字符串控制。 有关格式化指令的完整列表,请参阅 strftime() 和 strptime() 行为 部分。
- time.__format__(format)
- 与 time.strftime() 相同。 这使得在使用 str.format() 时为 time 对象指定格式字符串成为可能。 请参阅部分 strftime() 和 strptime() 行为 。
- time.utcoffset()
- 如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.utcoffset(None)
,如果后者不返回None
,则引发异常或一个 timedelta 对象,表示大小小于一天的整数分钟。
- time.dst()
- 如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.dst(None)
,如果后者不返回None
,则引发异常,或 timedelta 对象,表示大小小于一天的整数分钟。
- time.tzname()
- 如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.tzname(None)
,如果后者不返回None
,则引发异常或字符串对象。
示例:
>>> from datetime import time, tzinfo, timedelta
>>> class GMT1(tzinfo):
... def utcoffset(self, dt):
... return timedelta(hours=1)
... def dst(self, dt):
... return timedelta(0)
... def tzname(self,dt):
... return "Europe/Prague"
...
>>> t = time(12, 10, 30, tzinfo=GMT1())
>>> t
datetime.time(12, 10, 30, tzinfo=<GMT1 object at 0x...>)
>>> gmt = GMT1()
>>> t.isoformat()
'12:10:30+01:00'
>>> t.dst()
datetime.timedelta(0)
>>> t.tzname()
'Europe/Prague'
>>> t.strftime("%H:%M:%S %Z")
'12:10:30 Europe/Prague'
>>> 'The {} is {:%H:%M}.'.format("time", t)
'The time is 12:10.'
8.1.6. 资讯对象
- class datetime.tzinfo
这是一个抽象基类,这意味着不应直接实例化此类。 您需要派生一个具体的子类,并且(至少)提供您使用的 datetime 方法所需的标准 tzinfo 方法的实现。 datetime 模块不提供 tzinfo 的任何具体子类。
tzinfo(的具体子类)的实例可以传递给 datetime 和 time 对象的构造函数。 后一种对象将它们的属性视为本地时间,而 tzinfo 对象支持显示本地时间与 UTC 的偏移量、时区名称和 DST 偏移量的方法,所有这些都与日期或时间相关对象传递给他们。
酸洗的特殊要求:tzinfo 子类必须有一个
__init__()
方法,可以不带参数调用,否则它可以被酸洗,但可能不会再次被取消酸洗。 这是一项技术要求,未来可能会放宽。tzinfo 的具体子类可能需要实现以下方法。 究竟需要哪些方法取决于感知 datetime 对象的用途。 如果有疑问,只需实现所有这些。
- tzinfo.utcoffset(self, dt)
返回本地时间与 UTC 的偏移量,以 UTC 以东的分钟数为单位。 如果当地时间在 UTC 以西,这应该是负数。 请注意,这是与 UTC 的总偏移量; 例如,如果 tzinfo 对象同时表示时区和 DST 调整,则 utcoffset() 应返回它们的总和。 如果 UTC 偏移量未知,则返回
None
。 否则返回的值必须是一个 timedelta 对象,它指定了 -1439 到 1439 范围内的整数分钟数(1440 = 24*60;偏移量必须小于一天)。 utcoffset() 的大多数实现可能看起来像这两个之一:return CONSTANT # fixed-offset class return CONSTANT + self.dst(dt) # daylight-aware class
如果 utcoffset() 不返回
None
,dst() 也不应该返回None
。utcoffset() 的默认实现会引发
NotImplementedError
。
- tzinfo.dst(self, dt)
返回夏令时 (DST) 调整,以 UTC 以东的分钟数为单位,如果 DST 信息未知,则返回
None
。 如果 DST 无效,则返回timedelta(0)
。 如果 DST 有效,则将偏移量作为 timedelta 对象返回(有关详细信息,请参阅 utcoffset())。 请注意,如果适用,DST 偏移量已添加到 utcoffset() 返回的 UTC 偏移量中,因此除非您有兴趣获得,否则无需咨询 dst()单独的夏令时信息。 例如, datetime.timetuple() 调用其 tzinfo 属性的 dst() 方法来确定应如何设置tm_isdst
标志,以及tzinfo.fromutc() 调用 dst() 来解释跨时区时 DST 的变化。tzinfo 子类的实例 tz 对标准时间和日光时间进行建模在这个意义上必须是一致的:
tz.utcoffset(dt) - tz.dst(dt)
必须为每个 datetime dt 和
dt.tzinfo == tz
返回相同的结果对于正常的 tzinfo 子类,此表达式产生时区的“标准偏移量”,这不应该取决于日期或时间,而只取决于地理位置。 datetime.astimezone()的实现依赖于此,但无法检测违规; 程序员有责任确保它。 如果 tzinfo 子类不能保证这一点,它可能能够覆盖 tzinfo.fromutc() 的默认实现,以便与astimezone()
一起正常工作。dst() 的大多数实现可能看起来像这两个之一:
def dst(self, dt): # a fixed-offset class: doesn't account for DST return timedelta(0)
或者
def dst(self, dt): # Code to set dston and dstoff to the time zone's DST # transition times based on the input dt.year, and expressed # in standard local time. Then if dston <= dt.replace(tzinfo=None) < dstoff: return timedelta(hours=1) else: return timedelta(0)
dst() 的默认实现引发
NotImplementedError
。
- tzinfo.tzname(self, dt)
以字符串形式返回与 datetime 对象 dt 对应的时区名称。 datetime 模块没有定义任何关于字符串名称的内容,也没有要求它有什么特别的含义。 例如,“GMT”、“UTC”、“-500”、“-5:00”、“EDT”、“US/Eastern”、“America/New York”都是有效的回复。 如果字符串名称未知,则返回
None
。 请注意,这是一种方法而不是固定字符串,主要是因为某些 tzinfo 子类希望根据传递的 dt 的特定值返回不同的名称,特别是如果 tzinfo 类正在考虑白天时间。tzname() 的默认实现引发
NotImplementedError
。
这些方法由 datetime 或 time 对象调用,以响应它们的同名方法。 datetime 对象将自身作为参数传递,而 time 对象将 None
作为参数传递。 因此,tzinfo 子类的方法应准备好接受 None
或类 datetime 的 dt 参数。
当 None
被传递时,由类设计者决定最佳响应。 例如,如果类希望声明时间对象不参与 tzinfo 协议,则返回 None
是合适的。 utcoffset(None)
返回标准 UTC 偏移量可能更有用,因为没有其他约定可用于发现标准偏移量。
当传递 datetime 对象以响应 datetime 方法时,dt.tzinfo
与 self 是相同的对象。 tzinfo 方法可以依赖于此,除非用户代码直接调用 tzinfo 方法。 目的是 tzinfo 方法将 dt 解释为本地时间,而无需担心其他时区的对象。
还有一个 tzinfo 方法,子类可能希望覆盖:
- tzinfo.fromutc(self, dt)
这是从默认的 datetime.astimezone() 实现调用的。 从那里调用时,
dt.tzinfo
是 self,并且 dt 的日期和时间数据将被视为表示 UTC 时间。 fromutc() 的目的是调整日期和时间数据,在 self 的本地时间返回一个等效的日期时间。大多数 tzinfo 子类应该能够毫无问题地继承默认的 fromutc() 实现。 它足够强大,可以处理固定偏移时区,以及同时考虑标准时间和夏令时的时区,后者即使 DST 过渡时间在不同年份有所不同。 默认 fromutc() 实现可能无法在所有情况下正确处理的时区示例是标准偏移量(来自 UTC)取决于经过的特定日期和时间,这可能出于政治原因而发生.
astimezone()
和 fromutc() 的默认实现可能不会产生您想要的结果,如果结果是跨越标准偏移量变化那一刻的小时之一。跳过错误情况的代码,默认的 fromutc() 实现如下:
def fromutc(self, dt): # raise ValueError error if dt.tzinfo is not self dtoff = dt.utcoffset() dtdst = dt.dst() # raise ValueError if dtoff is None or dtdst is None delta = dtoff - dtdst # this is self's standard offset if delta: dt += delta # convert to standard local time dtdst = dt.dst() # raise ValueError if dtdst is None if dtdst: return dt + dtdst else: return dt
示例 tzinfo 类:
from datetime import tzinfo, timedelta, datetime
ZERO = timedelta(0)
HOUR = timedelta(hours=1)
# A UTC class.
class UTC(tzinfo):
"""UTC"""
def utcoffset(self, dt):
return ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return ZERO
utc = UTC()
# A class building tzinfo objects for fixed-offset time zones.
# Note that FixedOffset(0, "UTC") is a different way to build a
# UTC tzinfo object.
class FixedOffset(tzinfo):
"""Fixed offset in minutes east from UTC."""
def __init__(self, offset, name):
self.__offset = timedelta(minutes = offset)
self.__name = name
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return ZERO
# A class capturing the platform's idea of local time.
import time as _time
STDOFFSET = timedelta(seconds = -_time.timezone)
if _time.daylight:
DSTOFFSET = timedelta(seconds = -_time.altzone)
else:
DSTOFFSET = STDOFFSET
DSTDIFF = DSTOFFSET - STDOFFSET
class LocalTimezone(tzinfo):
def utcoffset(self, dt):
if self._isdst(dt):
return DSTOFFSET
else:
return STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return DSTDIFF
else:
return ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, 0)
stamp = _time.mktime(tt)
tt = _time.localtime(stamp)
return tt.tm_isdst > 0
Local = LocalTimezone()
# A complete implementation of current DST rules for major US time zones.
def first_sunday_on_or_after(dt):
days_to_go = 6 - dt.weekday()
if days_to_go:
dt += timedelta(days_to_go)
return dt
# US DST Rules
#
# This is a simplified (i.e., wrong for a few cases) set of rules for US
# DST start and end times. For a complete and up-to-date set of DST rules
# and timezone definitions, visit the Olson Database (or try pytz):
# http://www.twinsun.com/tz/tz-link.htm
# http://sourceforge.net/projects/pytz/ (might not be up-to-date)
#
# In the US, since 2007, DST starts at 2am (standard time) on the second
# Sunday in March, which is the first Sunday on or after Mar 8.
DSTSTART_2007 = datetime(1, 3, 8, 2)
# and ends at 2am (DST time; 1am standard time) on the first Sunday of Nov.
DSTEND_2007 = datetime(1, 11, 1, 1)
# From 1987 to 2006, DST used to start at 2am (standard time) on the first
# Sunday in April and to end at 2am (DST time; 1am standard time) on the last
# Sunday of October, which is the first Sunday on or after Oct 25.
DSTSTART_1987_2006 = datetime(1, 4, 1, 2)
DSTEND_1987_2006 = datetime(1, 10, 25, 1)
# From 1967 to 1986, DST used to start at 2am (standard time) on the last
# Sunday in April (the one on or after April 24) and to end at 2am (DST time;
# 1am standard time) on the last Sunday of October, which is the first Sunday
# on or after Oct 25.
DSTSTART_1967_1986 = datetime(1, 4, 24, 2)
DSTEND_1967_1986 = DSTEND_1987_2006
class USTimeZone(tzinfo):
def __init__(self, hours, reprname, stdname, dstname):
self.stdoffset = timedelta(hours=hours)
self.reprname = reprname
self.stdname = stdname
self.dstname = dstname
def __repr__(self):
return self.reprname
def tzname(self, dt):
if self.dst(dt):
return self.dstname
else:
return self.stdname
def utcoffset(self, dt):
return self.stdoffset + self.dst(dt)
def dst(self, dt):
if dt is None or dt.tzinfo is None:
# An exception may be sensible here, in one or both cases.
# It depends on how you want to treat them. The default
# fromutc() implementation (called by the default astimezone()
# implementation) passes a datetime with dt.tzinfo is self.
return ZERO
assert dt.tzinfo is self
# Find start and end times for US DST. For years before 1967, return
# ZERO for no DST.
if 2006 < dt.year:
dststart, dstend = DSTSTART_2007, DSTEND_2007
elif 1986 < dt.year < 2007:
dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006
elif 1966 < dt.year < 1987:
dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986
else:
return ZERO
start = first_sunday_on_or_after(dststart.replace(year=dt.year))
end = first_sunday_on_or_after(dstend.replace(year=dt.year))
# Can't compare naive to aware objects, so strip the timezone from
# dt first.
if start <= dt.replace(tzinfo=None) < end:
return HOUR
else:
return ZERO
Eastern = USTimeZone(-5, "Eastern", "EST", "EDT")
Central = USTimeZone(-6, "Central", "CST", "CDT")
Mountain = USTimeZone(-7, "Mountain", "MST", "MDT")
Pacific = USTimeZone(-8, "Pacific", "PST", "PDT")
请注意,在 DST 过渡点,tzinfo 子类中每年有两次不可避免的微妙之处,既考虑了标准时间,也考虑了夏令时。 为具体起见,请考虑美国东部时间 (UTC -0500),其中 EDT 在 3 月的第二个星期日的 1:59 (EST) 之后的分钟开始,并在 11 月的第一个星期日的 1:59 (EDT) 之后的分钟结束:
UTC 3:MM 4:MM 5:MM 6:MM 7:MM 8:MM
EST 22:MM 23:MM 0:MM 1:MM 2:MM 3:MM
EDT 23:MM 0:MM 1:MM 2:MM 3:MM 4:MM
start 22:MM 23:MM 0:MM 1:MM 3:MM 4:MM
end 23:MM 0:MM 1:MM 1:MM 2:MM 3:MM
当 DST 开始时(“开始”行),本地挂钟从 1:59 跳到 3:00。 当天形式为 2:MM 的挂墙时间实际上没有意义,因此 astimezone(Eastern)
不会在 DST 开始当天提供 hour == 2
的结果。 为了使 astimezone()
做出此保证,rzinfo.dst()
方法必须考虑“失踪小时”(东部时间为 2:MM)中的时间为白天。
当 DST 结束(“结束”行)时,可能会出现一个更糟糕的问题:在当地的挂钟时间中,有一个小时无法明确拼写:夏令时的最后一个小时。 在东部,这是日光时间结束时 5:MM UTC 形式的时间。 当地挂钟再次从 1:59(白天时间)跳回到 1:00(标准时间)。 1:MM 形式的本地时间是不明确的。 astimezone()
通过将两个相邻的 UTC 小时映射到同一个本地小时来模拟本地时钟的行为。 在东部示例中,格式为 5:MM 和 6:MM 的 UTC 时间在转换为东部时都映射为 1:MM。 为了让 astimezone()
做出这个保证,tzinfo.dst() 方法必须将“重复时间”中的时间考虑为标准时间。 这很容易安排,如示例中所示,通过以时区的标准本地时间表示 DST 切换时间。
不能承受这种歧义的应用程序应该避免使用混合 tzinfo 子类; 使用 UTC 或任何其他固定偏移量 tzinfo 子类(例如仅表示 EST(固定偏移量 -5 小时)或仅代表 EDT(固定偏移量 -4 小时)的类时没有歧义。
也可以看看
- 派兹
标准库没有 tzinfo 实例,但有一个第三方库将 IANA 时区数据库 (也称为 Olson 数据库)引入 Python:pytz[ X197X]。
pytz 包含最新信息,推荐使用。
- IANA 时区数据库
时区数据库(通常称为 tz 或 zoneinfo)包含代表全球许多代表性地点的当地时间历史的代码和数据。 它会定期更新,以反映政治机构对时区边界、UTC 偏移量和夏令时规则所做的更改。
8.1.7. strftime()和strptime()行为
date、datetime和time对象都支持strftime(format)
方法,在显式格式控制下创建表示时间的字符串细绳。 从广义上讲,d.strftime(fmt)
的作用类似于 time 模块的 time.strftime(fmt, d.timetuple())
,尽管并非所有对象都支持 timetuple()
方法。
相反,datetime.strptime() 类方法从表示日期和时间的字符串以及相应的格式字符串创建一个 datetime 对象。 datetime.strptime(date_string, format)
等价于 datetime(*(time.strptime(date_string, format)[0:6]))
,除非格式包含亚秒分量或时区偏移信息,datetime.strptime
支持但被 time.strptime
丢弃.
对于 time 对象,不应使用年、月和日的格式代码,因为时间对象没有这些值。 如果无论如何都使用它们,则用 1900
代替年,用 1
代替月和日。
对于 date 对象,不应使用小时、分钟、秒和微秒的格式代码,因为 date 对象没有这些值。 如果无论如何都使用它们,0
将替换它们。
支持的全套格式代码因平台而异,因为 Python 调用了平台 C 库的 strftime()
函数,平台变异是常见的。 要查看您的平台支持的完整格式代码集,请参阅 strftime(3) 文档。
出于同样的原因,处理包含无法在当前语言环境的字符集中表示的 Unicode 代码点的格式字符串也是平台相关的。 在某些平台上,这样的代码点在输出中保持完整,而在其他平台上,strftime
可能会引发 UnicodeError
或返回一个空字符串。
以下是 C 标准(1989 版)要求的所有格式代码的列表,这些代码适用于具有标准 C 实现的所有平台。 请注意,C 标准的 1999 版本添加了额外的格式代码。
strftime()
工作的确切年份范围也因平台而异。 无论平台如何,1900 年之前的年份都不能使用。
指令 | 意义 | 示例 | 笔记 |
---|---|---|---|
%a
|
工作日作为语言环境的缩写名称。 |
周日、周一、...、周六(en_US); 所以,Mo,...,Sa (de_DE) |
(1) |
%A
|
工作日作为语言环境的全名。 |
星期日、星期一、……、星期六(en_US); Sonntag, Montag, ..., Samstag (de_DE) |
(1) |
%w
|
工作日为十进制数,其中 0 是星期日,6 是星期六。 | 0, 1, ..., 6 | |
%d
|
以零填充的十进制数表示的月份中的某天。 | 01, 02, …, 31 | |
%b
|
月份作为语言环境的缩写名称。 |
一月、二月、...、十二月(en_US); 一月,二月,...,德兹(de_DE) |
(1) |
%B
|
月份作为语言环境的全名。 |
一月、二月、……、十二月(en_US); 一月、二月、...、十二月 (de_DE) |
(1) |
%m
|
以零填充的十进制数表示的月份。 | 01, 02, …, 12 | |
%y
|
没有世纪的年份作为零填充的十进制数。 | 00, 01, …, 99 | |
%Y
|
以世纪为十进制数的年份。 | 1970, 1988, 2001, 2013 | |
%H
|
小时(24 小时制)作为补零的十进制数。 | 00, 01, …, 23 | |
%I
|
小时(12 小时制)作为用零填充的十进制数。 | 01, 02, …, 12 | |
%p
|
区域设置相当于 AM 或 PM。 |
上午、下午(en_US); 上午,下午(de_DE) |
(1), (2) |
%M
|
分钟作为用零填充的十进制数。 | 00, 01, …, 59 | |
%S
|
第二个是用零填充的十进制数。 | 00, 01, …, 59 | (3) |
%f
|
微秒为十进制数,左侧补零。 | 000000, 000001, ..., 999999 | (4) |
%z
|
+HHMM 或 -HHMM 形式的 UTC 偏移量(如果对象是幼稚的,则为空字符串)。 | (空)、+0000、-0400、+1030 | (5) |
%Z
|
时区名称(如果对象是幼稚的,则为空字符串)。 | (空)、UTC、EST、CST | |
%j
|
以零填充的十进制数表示的一年中的第几天。 | 001, 002, …, 366 | |
%U
|
一年中的周数(星期日作为一周的第一天)作为零填充的十进制数。 新年第一个星期日之前的所有日子都被视为第 0 周。 | 00, 01, …, 53 | (6) |
%W
|
以十进制数表示的一年中的周数(星期一为一周的第一天)。 新年中第一个星期一之前的所有日子都被视为第 0 周。 | 00, 01, …, 53 | (6) |
%c
|
区域设置的适当日期和时间表示。 |
1988 年 8 月 16 日星期二 21:30:00(en_US); 1988 年 8 月 16 日 21:30:00 (de_DE) |
(1) |
%x
|
区域设置的适当日期表示。 |
88 年 8 月 16 日(无); 1988 年 8 月 16 日(en_US); 16.08.1988 (de_DE) |
(1) |
%X
|
区域设置的适当时间表示。 |
21:30:00 (en_US); 21:30:00 (de_DE) |
(1) |
%%
|
文字 '%' 字符。
|
% |
注意事项:
因为格式取决于当前的语言环境,所以在对输出值进行假设时应该小心。 字段顺序会有所不同(例如,“月/日/年”与“日/月/年”),并且输出可能包含使用区域设置的默认编码的 Unicode 字符(例如,如果当前区域设置为
ja_JP
,默认编码可以是eucJP
、SJIS
或utf-8
中的任何一种;使用locale.getlocale()确定当前语言环境的编码)。当与
strptime()
方法一起使用时,如果%I
指令用于解析小时,则%p
指令仅影响输出小时字段。%f
是 C 标准中格式字符集的扩展(但在日期时间对象中单独实现,因此始终可用)。 当与strptime()
方法一起使用时,%f
指令接受 1 到 6 位数字和右侧的零填充。2.6 版中的新功能。
对于 naive 对象,
%z
和%Z
格式代码被替换为空字符串。对于有意识的对象:
%z
utcoffset()
转换为 +HHMM 或 -HHMM 形式的 5 个字符的字符串,其中 HH 是给出 UTC 偏移小时数的 2 位字符串,MM 是给出数字的 2 位字符串UTC 偏移分钟数。 例如,如果utcoffset()
返回timedelta(hours=-3, minutes=-30)
,则%z
被替换为字符串'-0330'
。%Z
如果
tzname()
返回None
,则%Z
被替换为空字符串。 否则%Z
被返回值替换,该值必须是一个字符串。
当与
strptime()
方法一起使用时,%U
和%W
仅在指定了星期几和年份时用于计算。
脚注
- 1
- 如果,也就是说,我们忽略相对论的影响