datetime — 基本日期和时间类型 — Python 文档
datetime — 基本日期和时间类型
源代码: :source:`Lib/datetime.py`
datetime 模块提供了以简单和复杂方式操作日期和时间的类。 虽然支持日期和时间算术,但实现的重点是高效的属性提取以进行输出格式化和操作。 有关相关功能,另请参阅 time 和 calendar 模块。
有两种日期和时间对象:“naive”和“aware”。
感知对象具有足够的适用算法和政治时间调整知识,例如时区和夏令时信息,以相对于其他感知对象定位自身。 一个有意识的对象被用来表示一个特定的时刻,它是不可解释的 1。
一个天真的对象不包含足够的信息来明确地相对于其他日期/时间对象定位自己。 一个简单的对象是否代表协调世界时 (UTC)、本地时间或其他时区的时间完全取决于程序,就像特定数字是否代表米、英里或质量取决于程序一样。 朴素的对象易于理解和使用,但代价是忽略了现实的某些方面。
对于需要感知对象的应用程序,datetime 和 time 对象有一个可选的时区信息属性,tzinfo
,可以设置为抽象子类的实例tzinfo 类。 这些 tzinfo 对象捕获有关 UTC 时间偏移量、时区名称以及夏令时是否生效的信息。 请注意,datetime 模块仅提供一个具体的 tzinfo 类,即 timezone 类。 timezone 类可以表示与 UTC 有固定偏移的简单时区,例如 UTC 本身或北美 EST 和 EDT 时区。 在更深层次的细节支持时区取决于应用程序。 世界各地的时间调整规则政治性多于理性,变化频繁,除UTC之外没有适用于所有应用的标准。
datetime 模块导出以下常量:
可用类型
- class datetime.timezone
将 tzinfo 抽象基类实现为与 UTC 的固定偏移量的类。
3.2 版中的新功能。
这些类型的对象是不可变的。
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
timezone
time
date
datetime
timedelta 对象
timedelta 对象表示持续时间,即两个日期或时间之间的差异。
- class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
所有参数都是可选的,默认为
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)(6) |
t1 = t2 * i or t1 = i * t2
|
Delta 乘以一个整数。 之后 t1 // i == t2 为真,前提是 i != 0 。
|
一般来说,t1 * i == t1 * (i-1) + t1 是真的。 (1) | |
t1 = t2 * f or t1 = f * t2
|
Delta 乘以浮点数。 结果使用舍入到偶数舍入到最接近的 timedelta.resolution 倍数。 |
f = t2 / t3
|
总持续时间 t2 按间隔单位 t3 的除法 (3)。 返回一个 float 对象。 |
t1 = t2 / f or t1 = t2 / i
|
Delta 除以浮点数或整数。 结果使用舍入到偶数舍入到最接近的 timedelta.resolution 倍数。 |
t1 = t2 // i 或 t1 = t2 // t3
|
计算地板并丢弃剩余部分(如果有)。 在第二种情况下,返回一个整数。 (3) |
t1 = t2 % t3
|
余数计算为 timedelta 对象。 (3) |
q, r = divmod(t1, t2)
|
计算商和余数:q = t1 // t2 (3) 和 r = t1 % t2 。 q 是一个整数,r 是一个 timedelta 对象。
|
+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)
|
返回 timedelta 对象的字符串表示,作为具有规范属性值的构造函数调用。 |
笔记:
这是准确的,但可能会溢出。
这是准确的,不能溢出。
除以 0 会引发 ZeroDivisionError。
-timedelta.max 不能表示为 timedelta 对象。
timedelta 对象的字符串表示与它们的内部表示类似地标准化。 这导致负时间增量的一些不寻常的结果。 例如:
>>> timedelta(hours=-5) datetime.timedelta(days=-1, seconds=68400) >>> print(_) -1 day, 19:00:00
表达式
t2 - t3
将始终等于表达式t2 + (-t3)
,除非 t3 等于timedelta.max
; 在这种情况下,前者会产生结果,而后者会溢出。
除了上面列出的操作 timedelta 对象支持某些与 date 和 datetime 对象的加法和减法(见下文)。
在 3.2 版中更改: 现在支持 timedelta 对象与另一个 timedelta 对象的底除法和真正除法,以及余数运算和 divmod () 函数。 现在支持 [X38X]timedelta 对象与 float 对象的真正除法和乘法。
支持 timedelta 对象与 timedelta 对象的比较,表示较小的持续时间被认为是较小的 timedelta。 为了阻止混合类型比较返回到按对象地址进行的默认比较,当将 timedelta 对象与不同类型的对象进行比较时,会引发 TypeError,除非比较是 ==
或 !=
。 后一种情况分别返回 False 或 True。
timedelta 对象是 hashable(可用作字典键),支持高效酸洗,并且在布尔上下文中,timedelta 对象被认为是真当且仅当它不等于 timedelta(0)
。
实例方法:
- timedelta.total_seconds()
返回持续时间中包含的总秒数。 相当于
td / timedelta(seconds=1)
。 对于秒以外的间隔单位,直接使用除法形式(例如td / timedelta(microseconds=1)
)。请注意,对于非常大的时间间隔(在大多数平台上超过 270 年),此方法将失去微秒精度。
3.2 版中的新功能。
用法示例:
>>> 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(days=3650), 10)
>>> nine_years = ten_years - year
>>> nine_years, nine_years.days // 365
(datetime.timedelta(days=3285), 9)
>>> three_years = nine_years // 3
>>> three_years, three_years.days // 365
(datetime.timedelta(days=1095), 3)
>>> abs(three_years - ten_years) == 2 * three_years + year
True
日期对象
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()返回。 这可能会引发 OverflowError,如果时间戳超出平台 C
localtime()
函数支持的值范围,并且localtime()
上的 OSError 失败. 这通常被限制在 1970 年到 2038 年之间。 请注意,在时间戳概念中包含闰秒的非 POSIX 系统上,fromtimestamp() 会忽略闰秒。在 3.3 版更改:引发 OverflowError 而不是 ValueError 如果时间戳超出平台 C
localtime()
函数支持的值范围. 在localtime()
失败时引发 OSError 而不是 ValueError。
- classmethod date.fromordinal(ordinal)
- 返回对应于预测格列高利序数的日期,其中第 1 年的 1 月 1 日的序数为 1。 除非
1 <= ordinal <= date.max.toordinal()
,否则会引发 ValueError。 对于任何日期 d、date.fromordinal(d.toordinal()) == d
。
- classmethod date.fromisoformat(date_string)
以 date.isoformat() 发出的格式返回与 date_string 对应的 date。 具体来说,此函数支持格式为
YYYY-MM-DD
的字符串。警告
这不支持解析任意 ISO 8601 字符串 - 它仅用作 date.isoformat() 的逆操作。
3.7 版中的新功能。
类属性:
- 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。 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=self.year, month=self.month, day=self.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.'
日期时间对象
datetime 对象是包含来自 date 对象和 time 对象的所有信息的单个对象。 与 date 对象一样,datetime 假定当前的公历向两个方向扩展; 就像一个时间对象,datetime 假设每天正好有 3600*24 秒。
构造函数:
- class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
年、月和日参数是必需的。 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
,fold in [0, 1]
。
如果给出这些范围之外的参数,则会引发 ValueError。
3.6 新功能: 添加
fold
参数。
其他构造函数,所有类方法:
- classmethod datetime.today()
- 返回当前本地日期时间,使用 tzinfo
None
。 这相当于datetime.fromtimestamp(time.time())
。 另见 now()、fromtimestamp()。
- classmethod datetime.now(tz=None)
返回当前本地日期和时间。 如果可选参数 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 对象。 可以通过调用datetime.now(timezone.utc)
获得感知的当前 UTC 日期时间。 另见 now()。
- classmethod datetime.fromtimestamp(timestamp, tz=None)
返回POSIX时间戳对应的本地日期时间,如time.time()返回。 如果可选参数 tz 为
None
或未指定,则时间戳将转换为平台的本地日期和时间,并且返回的 datetime 对象是朴素的。如果tz不是
None
,则必须是tzinfo子类的实例,时间戳转换为tz的时区. 在这种情况下,结果等同于tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))
。fromtimestamp() 可能会引发 OverflowError,如果时间戳超出平台 C
localtime()
或gmtime()
函数支持的值范围,以及localtime()
或gmtime()
故障上的 OSError。 这通常被限制在 1970 年到 2038 年之间。 请注意,在时间戳概念中包含闰秒的非 POSIX 系统上,fromtimestamp() 会忽略闰秒,然后可能有两个相差一秒的时间戳产生相同的 ]datetime 对象。 另见 utcfromtimestamp()。在 3.3 版更改:如果时间戳超出平台 C 支持的值范围
localtime()
或gmtime()
功能。 在localtime()
或gmtime()
失败时引发 OSError 而不是 ValueError。3.6 版更改: fromtimestamp() 可能会返回 fold 设置为 1 的实例。
- classmethod datetime.utcfromtimestamp(timestamp)
返回 POSIX 时间戳对应的 UTC datetime,带有 tzinfo
None
。 这可能会引发 OverflowError,如果时间戳超出平台 Cgmtime()
函数支持的值范围,并且gmtime()
上的 OSError 失败. 这通常被限制在 1970 年到 2038 年之间。要了解 datetime 对象,请调用 fromtimestamp():
datetime.fromtimestamp(timestamp, timezone.utc)
在 POSIX 兼容平台上,它等效于以下表达式:
datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=timestamp)
除了后一个公式始终支持完整的年份范围:介于 MINYEAR 和 MAXYEAR 之间。
在 3.3 版更改:引发 OverflowError 而不是 ValueError 如果时间戳超出平台 C
gmtime()
函数支持的值范围. 在gmtime()
失败时引发 OSError 而不是 ValueError。
- classmethod datetime.fromordinal(ordinal)
- 返回对应于预测格列高利序数的 datetime,其中第 1 年的 1 月 1 日的序数为 1。 除非
1 <= ordinal <= datetime.max.toordinal()
,否则会引发 ValueError。 结果的时分秒微秒均为0,tzinfo为None
。
- classmethod datetime.combine(date, time, tzinfo=self.tzinfo)
返回一个新的 datetime 对象,其日期分量等于给定的 date 对象,其时间分量等于给定的 time 对象。 如果提供了 tzinfo 参数,则其值用于设置结果的 tzinfo 属性,否则设置 time 的 tzinfo 属性] 参数被使用。
对于任何 datetime 对象 d、
d == datetime.combine(d.date(), d.time(), d.tzinfo)
。 如果 date 是 datetime 对象,则忽略其时间分量和 tzinfo 属性。在 3.6 版更改: 添加了 tzinfo 参数。
- classmethod datetime.fromisoformat(date_string)
以 date.isoformat() 和 datetime.isoformat() 发出的格式之一返回与 date_string 对应的 datetime。 具体来说,此函数支持格式为
YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]
的字符串,其中*
可以匹配任何单个字符。警告
这不支持解析任意 ISO 8601 字符串 - 它仅用作 datetime.isoformat() 的逆操作。 第三方软件包 dateutil 中提供了功能更全面的 ISO 8601 解析器
dateutil.parser.isoparse
。3.7 版中的新功能。
- classmethod datetime.strptime(date_string, format)
- 返回date_string对应的datetime,按照格式解析。 这相当于
datetime(*(time.strptime(date_string, format)[0:6]))
。 ValueError 如果 date_string 和格式不能被 time.strptime() 解析或者它返回一个不是时间元组的值,则会引发。 有关格式化指令的完整列表,请参阅 strftime() 和 strptime() 行为 。
类属性:
- 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
如果没有传递。
- datetime.fold
在
[0, 1]
中。 用于在重复间隔期间消除墙壁时间的歧义。 (当时钟在夏令时结束时回滚或当前区域的 UTC 偏移量因政治原因减少时,会出现重复间隔。)值 0 (1) 表示两个时刻中较早(较晚)的时刻相同的墙壁时间表示。3.6 版中的新功能。
支持的操作:
手术 | 结果 |
---|---|
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 属性,即使输入知道也不会进行时区调整。
从 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.time()
返回具有相同时、分、秒、微秒和折叠的 time 对象。 tzinfo 是
None
。 另见方法 timetz()。3.6 版更改: 折叠值复制到返回的 time 对象。
- datetime.replace(year=self.year, month=self.month, day=self.day, hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, * fold=0)
返回具有相同属性的日期时间,除了那些由指定的关键字参数赋予新值的属性。 请注意,可以指定
tzinfo=None
以从已知日期时间创建一个简单的日期时间,而无需转换日期和时间数据。3.6 新功能: 添加
fold
参数。
- datetime.astimezone(tz=None)
返回具有新的 tzinfo 属性 tz 的 datetime 对象,调整日期和时间数据,使结果与 self 的 UTC 时间相同,但在 tz 的本地时间。
如果提供,tz 必须是 tzinfo 子类的实例,并且其 utcoffset() 和 dst() 方法不得返回
None
。 如果 self 是 naive,则假定它表示系统时区中的时间。如果不带参数调用(或使用
tz=None
),则系统本地时区被假定为目标时区。 转换后的日期时间实例的.tzinfo
属性将设置为 timezone 的实例,其区域名称和偏移量从操作系统获取。如果
self.tzinfo
为tz,self.astimezone(tz)
等于self:不调整日期或时间数据。 否则结果是时区 tz 中的本地时间,表示与 self 相同的 UTC 时间:在astz = dt.astimezone(tz)
之后,astz - astz.utcoffset()
将具有相同的日期和时间数据为dt - dt.utcoffset()
。如果您只想将时区对象 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)
3.3 版变更:tz 现在可以省略。
3.6 版更改: astimezone() 方法现在可以在假定代表系统本地时间的朴素实例上调用。
- datetime.utcoffset()
如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.utcoffset(self)
,如果后者不返回None
,则引发异常或 timedelta 星等小于 1 天的对象。3.7 版更改: UTC 偏移量不限于整数分钟。
- datetime.dst()
如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.dst(self)
,如果后者不返回None
,则引发异常或 timedelta 星等小于 1 天的对象。3.7 版更改: DST 偏移量不限于整数分钟。
- 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。 请注意,如果 d.year 是MINYEAR
或MAXYEAR
并且 UTC 调整溢出一年边界,则可能会引发 OverflowError。
- datetime.toordinal()
- 返回日期的预测格列高利序数。 与
self.date().toordinal()
相同。
- datetime.timestamp()
返回对应于 datetime 实例的 POSIX 时间戳。 返回值是一个 float,类似于 time.time() 返回的值。
假设 Naive datetime 实例表示本地时间,并且此方法依赖于平台 C
mktime()
函数来执行转换。 由于 datetime 在许多平台上支持的值范围比mktime()
更广,因此此方法可能会在过去或将来很长时间内引发 OverflowError。对于有意识的 datetime 实例,返回值计算如下:
(dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()
3.3 版中的新功能。
3.6 版更改: timestamp() 方法使用 fold 属性来消除重复间隔期间的时间歧义。
笔记
没有方法可以直接从表示 UTC 时间的朴素 datetime 实例获取 POSIX 时间戳。 如果您的应用程序使用此约定并且您的系统时区未设置为 UTC,您可以通过提供
tzinfo=timezone.utc
来获取 POSIX 时间戳:timestamp = dt.replace(tzinfo=timezone.utc).timestamp()
或者直接计算时间戳:
timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)
- 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='T', timespec='auto')
以 ISO 8601 格式返回表示日期和时间的字符串,YYYY-MM-DDTHH:MM:SS.ffffff 或者,如果 microsecond 为 0,则 YYYY-MM-DDTHH:MM:SS
如果 utcoffset() 不返回
None
,则附加一个字符串,给出 UTC 偏移量:YYYY-MM-DDTHH:MM:SS.ffffff+HH:MM[:SS[. ffffff]] 或者,如果 microsecond 是 0 YYYY-MM-DDTHH:MM:SS+HH:MM[:SS[.ffffff]]。可选参数 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'
可选参数 timespec 指定要包含的时间附加分量的数量(默认值为
'auto'
)。 它可以是以下之一:'auto'
:如果 microsecond 为 0,则与'seconds'
相同,否则与'microseconds'
相同。'hours'
:包括两位 HH 格式的 hour。'milliseconds'
:包括全时,但将小数秒部分截断为毫秒。 HH:MM:SS.sss 格式。'microseconds'
:以 HH:MM:SS.ffffff 格式包括全职。
笔记
排除的时间分量被截断,而不是四舍五入。
ValueError 将在无效的 timespec 参数上引发。
>>> from datetime import datetime >>> datetime.now().isoformat(timespec='minutes') '2002-12-25T00:00' >>> dt = datetime(2015, 1, 1, 12, 30, 59, 0) >>> dt.isoformat(timespec='microseconds') '2015-01-01T12:30:59.000000'
3.6 新功能: 添加 timespec 参数。
- 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, timezone
>>> class KabulTz(tzinfo):
... # Kabul used +4 until 1945, when they moved to +4:30
... UTC_MOVE_DATE = datetime(1944, 12, 31, 20, tzinfo=timezone.utc)
... def utcoffset(self, dt):
... if dt.year < 1945:
... return timedelta(hours=4)
... elif (1945, 1, 1, 0, 0) <= dt.timetuple()[:5] < (1945, 1, 1, 0, 30):
... # If dt falls in the imaginary range, use fold to decide how
... # to resolve. See PEP495
... return timedelta(hours=4, minutes=(30 if dt.fold else 0))
... else:
... return timedelta(hours=4, minutes=30)
...
... def fromutc(self, dt):
... # A custom implementation is required for fromutc as
... # the input to this function is a datetime with utc values
... # but with a tzinfo set to self
... # See datetime.astimezone or fromtimestamp
...
... # Follow same validations as in datetime.tzinfo
... if not isinstance(dt, datetime):
... raise TypeError("fromutc() requires a datetime argument")
... if dt.tzinfo is not self:
... raise ValueError("dt.tzinfo is not self")
...
... if dt.replace(tzinfo=timezone.utc) >= self.UTC_MOVE_DATE:
... return dt + timedelta(hours=4, minutes=30)
... else:
... return dt + timedelta(hours=4)
...
... def dst(self, dt):
... return timedelta(0)
...
... def tzname(self, dt):
... if dt >= self.UTC_MOVE_DATE:
... return "+04:30"
... else:
... return "+04"
...
... def __repr__(self):
... return f"{self.__class__.__name__}()"
...
>>> tz1 = KabulTz()
>>> # Datetime before the change
>>> dt1 = datetime(1900, 11, 21, 16, 30, tzinfo=tz1)
>>> print(dt1.utcoffset())
4:00:00
>>> # Datetime after the change
>>> dt2 = datetime(2006, 6, 14, 13, 0, tzinfo=tz1)
>>> print(dt2.utcoffset())
4:30:00
>>> # Convert datetime to another time zone
>>> dt3 = dt2.astimezone(timezone.utc)
>>> dt3
datetime.datetime(2006, 6, 14, 8, 30, tzinfo=datetime.timezone.utc)
>>> dt2
datetime.datetime(2006, 6, 14, 13, 0, tzinfo=KabulTz())
>>> dt2.utctimetuple() == dt3.utctimetuple()
True
时间对象
时间对象表示一天中的(本地)时间,独立于任何特定的一天,并且可以通过 tzinfo 对象进行调整。
- class datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
所有参数都是可选的。 tzinfo 可以是
None
,或 tzinfo 子类的实例。 其余参数必须是以下范围内的整数:0 <= hour < 24
,0 <= minute < 60
,0 <= second < 60
,0 <= microsecond < 1000000
,fold in [0, 1]
。
如果给出这些范围之外的参数,则会引发 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.fold
在
[0, 1]
中。 用于在重复间隔期间消除墙壁时间的歧义。 (当时钟在夏令时结束时回滚或当前区域的 UTC 偏移量因政治原因减少时,会出现重复间隔。)值 0 (1) 表示两个时刻中较早(较晚)的时刻相同的墙壁时间表示。3.6 版中的新功能。
支持的操作:
time 与 time 的比较,其中 a 被认为小于 b 当 a 在 b 之前 及时。 如果一个比较是天真的而另一个知道,则在尝试进行订单比较时会引发 TypeError。 对于相等比较,朴素实例永远不等于有意识的实例。
如果两个比较数都知道,并且具有相同的 tzinfo 属性,则忽略公共的 tzinfo 属性并比较基准时间。 如果两个比较数都知道并且具有不同的 tzinfo 属性,则首先通过减去它们的 UTC 偏移量(从
self.utcoffset()
获得)来调整比较数。 为了阻止混合类型比较返回到按对象地址进行的默认比较,当 time 对象与不同类型的对象进行比较时,会引发 TypeError,除非比较是==
或!=
。 后一种情况分别返回 False 或 True。哈希,用作字典键
高效酸洗
在布尔上下文中,一个 time 对象总是被认为是真的。
3.5 版更改: 在 Python 3.5 之前,如果 time 对象在 UTC 中表示午夜,则它被认为是假的。 这种行为被认为是晦涩难懂且容易出错的,并已在 Python 3.5 中删除。 有关完整详细信息,请参阅 :issue:`13936`。
其他构造函数:
- classmethod time.fromisoformat(time_string)
以 time.isoformat() 发出的格式之一返回与 time_string 对应的 time。 具体来说,此函数支持格式为
HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]
的字符串。警告
这不支持解析任意 ISO 8601 字符串 - 它仅用作 time.isoformat() 的逆操作。
3.7 版中的新功能。
实例方法:
- time.replace(hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, * fold=0)
返回具有相同值的 time,除了那些由指定的关键字参数赋予新值的属性。 请注意,可以指定
tzinfo=None
以从感知 time 创建一个朴素的 time,而无需转换时间数据。3.6 新功能: 添加
fold
参数。
- time.isoformat(timespec='auto')
以 ISO 8601 格式返回表示时间的字符串,HH:MM:SS.ffffff 或者,如果 microsecond 为 0,则 HH:MM:SS 如果 utcoffset() 不返回 [ X157X],附加一个字符串,给出 UTC 偏移量:HH:MM:SS.ffffff+HH:MM[:SS[.ffffff]] 或者,如果 self.microsecond 为 0,则 HH:MM:SS+ HH:MM[:SS[.ffffff]]。
可选参数 timespec 指定要包含的时间附加分量的数量(默认值为
'auto'
)。 它可以是以下之一:'auto'
:如果 microsecond 为 0,则与'seconds'
相同,否则与'microseconds'
相同。'hours'
:包括两位 HH 格式的 hour。'milliseconds'
:包括全时,但将小数秒部分截断为毫秒。 HH:MM:SS.sss 格式。'microseconds'
:以 HH:MM:SS.ffffff 格式包括全职。
笔记
排除的时间分量被截断,而不是四舍五入。
ValueError 将在无效的 timespec 参数上引发。
>>> from datetime import time >>> time(hour=12, minute=34, second=56, microsecond=123456).isoformat(timespec='minutes') '12:34' >>> dt = time(hour=12, minute=34, second=56, microsecond=0) >>> dt.isoformat(timespec='microseconds') '12:34:56.000000' >>> dt.isoformat(timespec='auto') '12:34:56'
3.6 新功能: 添加 timespec 参数。
- 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 星等小于 1 天的对象。3.7 版更改: UTC 偏移量不限于整数分钟。
- time.dst()
如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.dst(None)
,如果后者不返回None
,则引发异常,或一个 timedelta 对象,其震级小于 1 天。3.7 版更改: DST 偏移量不限于整数分钟。
- time.tzname()
- 如果 tzinfo 是
None
,则返回None
,否则返回self.tzinfo.tzname(None)
,如果后者不返回None
,则引发异常或字符串对象。
例子:
>>> from datetime import time, tzinfo, timedelta
>>> class TZ1(tzinfo):
... def utcoffset(self, dt):
... return timedelta(hours=1)
... def dst(self, dt):
... return timedelta(0)
... def tzname(self,dt):
... return "+01:00"
... def __repr__(self):
... return f"{self.__class__.__name__}()"
...
>>> t = time(12, 10, 30, tzinfo=TZ1())
>>> t
datetime.time(12, 10, 30, tzinfo=TZ1())
>>> t.isoformat()
'12:10:30+01:00'
>>> t.dst()
datetime.timedelta(0)
>>> t.tzname()
'+01:00'
>>> t.strftime("%H:%M:%S %Z")
'12:10:30 +01:00'
>>> 'The {} is {:%H:%M}.'.format("time", t)
'The time is 12:10.'
tzinfo 对象
- class datetime.tzinfo
这是一个抽象基类,这意味着不应直接实例化此类。 您需要派生一个具体的子类,并且(至少)提供您使用的 datetime 方法所需的标准 tzinfo 方法的实现。 datetime 模块提供了一个简单的具体子类 tzinfo, timezone,可以表示与 UTC 有固定偏移的时区,例如 UTC 本身或北美 EST 和 EDT .
tzinfo(的具体子类)的实例可以传递给 datetime 和 time 对象的构造函数。 后者将它们的属性视为本地时间,而 tzinfo 对象支持显示本地时间与 UTC 的偏移量、时区名称和 DST 偏移量的方法,所有这些都与日期或时间相关对象传递给他们。
酸洗的特殊要求:tzinfo 子类必须有一个
__init__()
方法,可以不带参数调用,否则它可以被酸洗,但可能不会再次被取消酸洗。 这是一项技术要求,未来可能会放宽。tzinfo 的具体子类可能需要实现以下方法。 究竟需要哪些方法取决于感知 datetime 对象的用途。 如果有疑问,只需实现所有这些。
- tzinfo.utcoffset(dt)
返回本地时间与 UTC 的偏移量,作为 UTC 正东的 timedelta 对象。 如果当地时间在 UTC 以西,这应该是负数。 请注意,这是与 UTC 的总偏移量; 例如,如果 tzinfo 对象同时表示时区和 DST 调整,则 utcoffset() 应返回它们的总和。 如果 UTC 偏移量未知,则返回
None
。 否则返回的值必须是 timedelta 对象,严格介于-timedelta(hours=24)
和timedelta(hours=24)
之间(偏移量必须小于一天)。 utcoffset() 的大多数实现可能看起来像这两个之一:return CONSTANT # fixed-offset class return CONSTANT + self.dst(dt) # daylight-aware class
如果 utcoffset() 不返回
None
,dst() 也不应该返回None
。utcoffset() 的默认实现会引发 NotImplementedError。
3.7 版更改: UTC 偏移量不限于整数分钟。
- tzinfo.dst(dt)
如果 DST 信息未知,则返回夏令时 (DST) 调整,作为 timedelta 对象或
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。
3.7 版更改: DST 偏移量不限于整数分钟。
- tzinfo.tzname(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(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_examples.py 文件中有一些 tzinfo 类的例子:
from datetime import tzinfo, timedelta, datetime
ZERO = timedelta(0)
HOUR = timedelta(hours=1)
SECOND = timedelta(seconds=1)
# A class capturing the platform's idea of local time.
# (May result in wrong values on historical times in
# timezones where UTC offset and/or the DST rules had
# changed in the past.)
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 fromutc(self, dt):
assert dt.tzinfo is self
stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) // SECOND
args = _time.localtime(stamp)[:6]
dst_diff = DSTDIFF // SECOND
# Detect fold
fold = (args == _time.localtime(stamp - dst_diff))
return datetime(*args, microsecond=dt.microsecond,
tzinfo=self, fold=fold)
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) on the first Sunday of Nov.
DSTEND_2007 = datetime(1, 11, 1, 2)
# 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) 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, 2)
# 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)
# 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
def us_dst_range(year):
# Find start and end times for US DST. For years before 1967, return
# start = end for no DST.
if 2006 < year:
dststart, dstend = DSTSTART_2007, DSTEND_2007
elif 1986 < year < 2007:
dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006
elif 1966 < year < 1987:
dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986
else:
return (datetime(year, 1, 1), ) * 2
start = first_sunday_on_or_after(dststart.replace(year=year))
end = first_sunday_on_or_after(dstend.replace(year=year))
return start, end
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
start, end = us_dst_range(dt.year)
# Can't compare naive to aware objects, so strip the timezone from
# dt first.
dt = dt.replace(tzinfo=None)
if start + HOUR <= dt < end - HOUR:
# DST is in effect.
return HOUR
if end - HOUR <= dt < end:
# Fold (an ambiguous hour): use dt.fold to disambiguate.
return ZERO if dt.fold else HOUR
if start <= dt < start + HOUR:
# Gap (a non-existent hour): reverse the fold rule.
return HOUR if dt.fold else ZERO
# DST is off.
return ZERO
def fromutc(self, dt):
assert dt.tzinfo is self
start, end = us_dst_range(dt.year)
start = start.replace(tzinfo=self)
end = end.replace(tzinfo=self)
std_time = dt + self.stdoffset
dst_time = std_time + HOUR
if end <= dst_time < end + HOUR:
# Repeated hour
return std_time.replace(fold=1)
if std_time < start or dst_time >= end:
# Standard time
return std_time
if start <= std_time < end - HOUR:
# Daylight saving time
return dst_time
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
的结果。 例如,在 2016 年的 Spring forward transition 时,我们得到
>>> from datetime import datetime, timezone
>>> from tzinfo_examples import HOUR, Eastern
>>> u0 = datetime(2016, 3, 13, 5, tzinfo=timezone.utc)
>>> for i in range(4):
... u = u0 + i*HOUR
... t = u.astimezone(Eastern)
... print(u.time(), 'UTC =', t.time(), t.tzname())
...
05:00:00 UTC = 00:00:00 EST
06:00:00 UTC = 01:00:00 EST
07:00:00 UTC = 03:00:00 EDT
08:00:00 UTC = 04:00:00 EDT
当 DST 结束(“结束”行)时,可能会出现一个更糟糕的问题:在当地的挂钟时间中,有一个小时无法明确拼写:夏令时的最后一个小时。 在东部,这是日光时间结束时 5:MM UTC 形式的时间。 当地挂钟再次从 1:59(白天时间)跳回到 1:00(标准时间)。 1:MM 形式的本地时间是不明确的。 astimezone()
通过将两个相邻的 UTC 小时映射到同一个本地小时来模拟本地时钟的行为。 在东部示例中,格式为 5:MM 和 6:MM 的 UTC 时间在转换为东部时都映射为 1:MM,但较早的时间将 fold 属性设置为 0,而较晚的时间有它设置为 1。 例如,在 2016 年的回退过渡中,我们得到
>>> u0 = datetime(2016, 11, 6, 4, tzinfo=timezone.utc)
>>> for i in range(4):
... u = u0 + i*HOUR
... t = u.astimezone(Eastern)
... print(u.time(), 'UTC =', t.time(), t.tzname(), t.fold)
...
04:00:00 UTC = 00:00:00 EDT 0
05:00:00 UTC = 01:00:00 EDT 0
06:00:00 UTC = 01:00:00 EST 1
07:00:00 UTC = 02:00:00 EST 0
请注意,仅 fold 属性值不同的 datetime 实例在比较中被视为相等。
不能承受墙壁时间歧义的应用程序应明确检查 fold 属性的值或避免使用混合 tzinfo 子类; 使用 timezone 或任何其他固定偏移量 tzinfo 子类(例如仅表示 EST(固定偏移量 -5 小时)或仅表示 EDT(固定偏移量)的类时没有歧义-4个小时))。
也可以看看
- 日期工具.tz
标准库有 timezone 类用于处理与 UTC 和 timezone.utc 作为 UTC 时区实例的任意固定偏移量。
dateutil.tz 库将 IANA 时区数据库 (也称为 Olson 数据库)引入 Python,推荐使用。
- IANA 时区数据库
时区数据库(通常称为 tz、tzdata 或 zoneinfo)包含代表全球许多代表性位置的本地时间历史的代码和数据。 它会定期更新,以反映政治机构对时区边界、UTC 偏移量和夏令时规则所做的更改。
时区对象
timezone 类是 tzinfo 的子类,它的每个实例都代表一个由 UTC 固定偏移量定义的时区。 请注意,此类的对象不能用于表示一年中不同日期使用不同偏移量或对民用时间进行历史更改的位置的时区信息。
- class datetime.timezone(offset, name=None)
offset 参数必须指定为 timedelta 对象,表示本地时间和 UTC 之间的差异。 必须严格在
-timedelta(hours=24)
和timedelta(hours=24)
之间,否则会引发 ValueError。name 参数是可选的。 如果指定,它必须是一个字符串,将用作 datetime.tzname() 方法返回的值。
3.2 版中的新功能。
3.7 版更改: UTC 偏移量不限于整数分钟。
- timezone.utcoffset(dt)
返回构造 timezone 实例时指定的固定值。 dt 参数被忽略。 返回值是一个 timedelta 实例,等于本地时间和 UTC 之间的差异。
3.7 版更改: UTC 偏移量不限于整数分钟。
- timezone.tzname(dt)
返回构造 timezone 实例时指定的固定值。 如果构造函数中未提供 name,则
tzname(dt)
返回的名称由offset
的值生成,如下所示。 如果offset为timedelta(0)
,则名称为“UTC”,否则为字符串'UTC±HH:MM',其中±为offset
,HH的符号和MM分别是offset.hours
和offset.minutes
的两位数。在 3.6 版中更改: 从
offset=timedelta(0)
生成的名称现在是普通的“UTC”,而不是“UTC+00:00”。
- timezone.dst(dt)
- 始终返回
None
。
- timezone.fromutc(dt)
- 返回
dt + offset
。 dt 参数必须是一个可感知的 datetime 实例,其中tzinfo
设置为self
。
类属性:
- timezone.utc
- UTC 时区,
timezone(timedelta(0))
。
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
将替换它们。
对于 datetime.strptime() 类方法,默认值为 1900-01-01T00:00:00.000
:格式字符串中未指定的任何组件将从默认值中提取。 2
支持的全套格式代码因平台而异,因为 Python 调用了平台 C 库的 strftime()
函数,平台变异是常见的。 要查看您的平台支持的完整格式代码集,请参阅 strftime(3) 文档。
出于同样的原因,处理包含无法在当前语言环境的字符集中表示的 Unicode 代码点的格式字符串也是平台相关的。 在某些平台上,这样的代码点在输出中保持完整,而在其他平台上 strftime
可能会引发 UnicodeError 或返回一个空字符串。
以下是 C 标准(1989 版)要求的所有格式代码的列表,这些代码适用于具有标准 C 实现的所有平台。 请注意,C 标准的 1999 版本添加了额外的格式代码。
指示 | 意义 | 例子 | 笔记 |
---|---|---|---|
%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 | (9) |
%b
|
月份作为语言环境的缩写名称。 |
一月、二月、...、十二月(en_US); 一月,二月,...,德兹(de_DE) |
(1) |
%B
|
月份作为语言环境的全名。 |
一月、二月、……、十二月(en_US); 一月、二月、...、十二月 (de_DE) |
(1) |
%m
|
以零填充的十进制数表示的月份。 | 01, 02, …, 12 | (9) |
%y
|
没有世纪的年份作为零填充的十进制数。 | 00, 01, …, 99 | (9) |
%Y
|
以世纪为十进制数的年份。 | 0001, 0002, ..., 2013, 2014, ..., 9998, 9999 | (2) |
%H
|
小时(24 小时制)作为补零的十进制数。 | 00, 01, …, 23 | (9) |
%I
|
小时(12 小时制)作为用零填充的十进制数。 | 01, 02, …, 12 | (9) |
%p
|
区域设置相当于 AM 或 PM。 |
上午、下午(en_US); 上午,下午(de_DE) |
(1), (3) |
%M
|
分钟作为用零填充的十进制数。 | 00, 01, …, 59 | (9) |
%S
|
第二个是用零填充的十进制数。 | 00, 01, …, 59 | (4), (9) |
%f
|
微秒为十进制数,左侧补零。 | 000000, 000001, ..., 999999 | (5) |
%z
|
格式为 ±HHMM[SS[.ffffff]] 的 UTC 偏移量(如果对象是幼稚的,则为空字符串)。 | (空), +0000, -0400, +1030, +063415, -030712.345216 | (6) |
%Z
|
时区名称(如果对象是幼稚的,则为空字符串)。 | (空)、UTC、EST、CST | |
%j
|
以零填充的十进制数表示的一年中的第几天。 | 001, 002, …, 366 | (9) |
%U
|
一年中的周数(星期日作为一周的第一天)作为零填充的十进制数。 新年第一个星期日之前的所有日子都被视为第 0 周。 | 00, 01, …, 53 | (7), (9) |
%W
|
以十进制数表示的一年中的周数(星期一为一周的第一天)。 新年中第一个星期一之前的所有日子都被视为第 0 周。 | 00, 01, …, 53 | (7), (9) |
%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) |
%%
|
文字 '%' 字符。
|
% |
为方便起见,包含了 C89 标准不需要的几个附加指令。 这些参数都对应于 ISO 8601 日期值。 当与 strftime()
方法一起使用时,这些可能不适用于所有平台。 ISO 8601 年和 ISO 8601 周指令不能与上述年份和周数指令互换。 使用不完整或不明确的 ISO 8601 指令调用 strptime()
将引发 ValueError。
指示 | 意义 | 例子 | 笔记 |
---|---|---|---|
%G
|
ISO 8601 年,世纪代表包含 ISO 周大部分时间的年份 (%V )。
|
0001, 0002, ..., 2013, 2014, ..., 9998, 9999 | (8) |
%u
|
ISO 8601 工作日为十进制数,其中 1 是星期一。 | 1, 2, ..., 7 | |
%V
|
ISO 8601 周为十进制数,星期一为一周的第一天。 第 1 周是包含 1 月 4 日的那一周。 | 01, 02, …, 53 | (8), (9) |
3.6 新功能:添加了 %G
、%u
和 %V
。
笔记:
因为格式取决于当前的语言环境,所以在对输出值进行假设时应该小心。 字段顺序会有所不同(例如,“月/日/年”与“日/月/年”),并且输出可能包含使用区域设置的默认编码的 Unicode 字符(例如,如果当前区域设置为
ja_JP
,默认编码可以是eucJP
、SJIS
或utf-8
中的任何一种;使用locale.getlocale()确定当前语言环境的编码)。这
strptime()
方法可以解析完整 [1, 9999] 范围内的年份,但年份 < 1000 必须用零填充到 4 位宽度。3.2 版更改: 在以前的版本中,
strftime()
方法仅限于 >= 1900 年。3.3 版更改: 在 3.2 版中,
strftime()
方法被限制为年数 >= 1000。当与
strptime()
方法一起使用时,如果%I
指令用于解析小时,则%p
指令仅影响输出小时字段。当与
strptime()
方法一起使用时,%f
指令接受 1 到 6 位数字和右侧的零填充。%f
是 C 标准中格式字符集的扩展(但在日期时间对象中单独实现,因此始终可用)。对于 naive 对象,
%z
和%Z
格式代码被替换为空字符串。对于有意识的对象:
%z
utcoffset()
转换为 ±HHMM[SS[.ffffff]] 形式的字符串,其中 HH 是一个 2 位字符串,表示 UTC 偏移小时数,MM 是一个 2 位字符串,表示该数字UTC 偏移分钟数,SS 是一个 2 位字符串,给出 UTC 偏移秒数,ffffff 是一个 6 位字符串,给出 UTC 偏移微秒数。 当偏移量为整数秒时省略 ffffff 部分,当偏移量为整数分钟时省略 ffffff 和 SS 部分。 例如,如果utcoffset()
返回timedelta(hours=-3, minutes=-30)
,则%z
被替换为字符串'-0330'
。
3.7 版更改: UTC 偏移量不限于整数分钟。
3.7 版更改: 当
%z
指令提供给strptime()
方法时,UTC 偏移量可以有一个冒号作为小时、分钟和秒之间的分隔符。 例如,'+01:00:00'
将被解析为一小时的偏移量。 此外,提供'Z'
与'+00:00'
相同。%Z
如果
tzname()
返回None
,则%Z
被替换为空字符串。 否则%Z
被返回值替换,该值必须是一个字符串。
当与
strptime()
方法一起使用时,%U
和%W
仅在指定了星期几和日历年 (%Y
) 时用于计算.与
%U
和%W
类似,%V
仅用于在 [ X148X] 格式字符串。 另请注意,%G
和%Y
不可互换。当与
strptime()
方法一起使用时,前导零对于格式%d
、%m
、%H
、%I
、%M
、%S
、%J
、%U
、%W
和%V
。 格式%y
确实需要前导零。
脚注