8.1. datetime
— 基本日期和时间类型¶
源代码: Lib/datetime.py
datetime
模块提供处理日期和时间的类,既有简单的方式又有复杂的方式。虽然支持日期和时间算法,但实现的重点是为输出格式化和操作提供高效的属性提取。有关相关功能,另请参阅time
和calendar
模块。
有两种日期和时间类型:“naive” 和 “aware”。
aware 对象具有关于应用规则和时间调整的充分的信息,例如时区和夏令时信息,来定位相对其他aware 对象的位置。aware 对象用于表示时间的一个特定的时刻,它是明确无二的[1]。
naive 对象没有充分的信息来明确地相对其他日期/时间定位它自己。一个naive对象是表示协调世界时(UTC),本地时间还是某些其他时区的时间,完全取决于程序,就像某个特定数字对程序是代表米,英里还是质量一样。
对于需要aware对象的应用程序,datetime
和time
对象具有可选的时区信息属性tzinfo
,可以设置为抽象tzinfo
类的子类的一个实例。这些tzinfo
对象从UTC时间,时区名称和夏令时是否生效获得偏移量信息。请注意,datetime
模块只提供一个具体的tzinfo
类叫timezone
类。timezone
类可以用与UTC固定的偏移表示简单的时区,例如UTC本身或北美EST和EDT时区。支持更深层细节的时区取决于应用程序。世界各地的时间调整规则更加具有政治色彩而不是合乎理性,且经常变化,除了UTC之外,没有适合于每个应用的标准。
datetime
模块导出以下常量:
8.1.1. 可用类型¶
- class
datetime.
time
理想化的时间,与任何一个特定的日子无关,假设每天精确地具有24*60*60秒(这里没有“闰秒”的概念)。属性:
hour
、minute
、second
、microsecond
和tzinfo
。
- class
datetime.
timezone
实现
tzinfo
抽象基类的类,表示与UTC的固定偏移量。版本3.2中的新功能。
这些类型的对象是不可变的。
date
类型的对象总是naive的。
time
或datetime
类型的对象可能是naive的或aware的。如果d.tzinfo
不为None
且d.tzinfo.utcoffset(d)
不返回None
,则datetime
对象d是aware的。如果d.tzinfo
为None
或者d.tzinfo
不为None
但是d.tzinfo .utcoffset(d)
返回None
,则d是naive的。如果t.tzinfo
不为None
且t.tzinfo.utcoffset(None)
不返回None
,则time
对象t是aware的。否则,t是naive的。
Naive和aware之间的区别不适用于timedelta
对象。
子类之间的关系:
object
timedelta
tzinfo
timezone
time
date
datetime
8.1.2. timedelta
对象¶
timedelta
对象表示时间的间隔,即两个日期或时间之间的差值。
- class
datetime.
timedelta
(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)¶ 所有参数都是可选的且默认为
0
。参数可以是整数或浮点数,也可以是正数或负数。内部只存储days、seconds 和 microseconds 。 所有的参数都将转换成这三个单位:
- 1毫秒转换为1000微秒。
- 1分钟转换为60秒。
- 1小时转换为3600秒。
- 1周被转换为7天。
然后标准化days、seconds 和microseconds 使得它们的表示是唯一的:
0 微秒 1000000
0 <= seconds < 3600*24
(一天中的秒数)-999999999 天 999999999 t0>
如果有任何一个参数是浮点数并且有微秒数,则将所有参数剩余的小数微秒相加,并使用round-half-to-even规则将它们的和舍入到最接近的微秒。如果没有参数是浮点数,那么转换和标准化过程是精确的(没有损失信息)。
如果days的归一化值超出表示的范围,则会引发
OverflowError
。注意负数值的标准化起初可能让人吃惊。例如,
>>> from datetime import timedelta >>> d = timedelta(microseconds=-1) >>> (d.days, d.seconds, d.microseconds) (-1, 86399, 999999)
类属性有:
-
timedelta.
max
¶ 最大的
timedelta
对象,timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999)
。
注意,由于归一化,timedelta.max
> -timedelta.min
。-timedelta.max
不能表示成一个timedelta
对象。
实例属性(只读):
属性 | 值 |
---|---|
days | 介于-999999999和999999999之间(包括-999999999和999999999) |
seconds | 介于0和86399之间(包括0和86399) |
microseconds | 介于0和999999之间(包括0和999999) |
支持的操作:
操作 | 结果 |
---|---|
t1 = t2 + t3 | t2和t3的和。之后,t1-t2 == t3 and t1-t3 == t2为真。(1) |
t1 = t2 - t3 | t2和t3的差。之后t1 == t2 - t3 and t2 == t1 + t3为真。(1) |
t1 = t2 * i 或 t1 = i * t2 | Delta乘以一个整数。之后,如果i != 0 ,则t1 // i == t2为真。 |
通常,t1 * i == t1 * (i-1) + t1为真。(1) | |
t1 = t2 * f 或 t1 = f * t2 | Delta乘以一个浮点数。结果使用round-half-to-even舍入到timedelta.resolution最近的倍数。 |
f = t2 / t3 | t2除以t3(3)。返回一个float 对象。 |
t1 = t2 / f 或 t1 = t2 / i | Delta除以一个浮点数或整数。结果使用round-half-to-even舍入到timedelta.resolution最近的倍数。 |
t1 = t2 // i 或t1 = t2 // t3 | 计算商,余数(如果有的话)被丢弃。在第二种情况下,返回一个整数。(3) |
t1 = t2 % t3 | 计算余数,为一个timedelta 对象。(3) |
q, r = divmod(t1, t2) t0> | 计算商和余数: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] 形式返回一个字符串,其中对于负t D为负数。(5) |
repr(t) | 以datetime.timedelta(D[, S[, U]]) 形式返回一个字符串,其中对于负t D为负数。(5) |
注:
计算是精确的,但是可能出现溢出。
计算是精确的,且不会出现溢出。
除0引发
ZeroDivisionError
。- timedelta.max不能表示成一个
timedelta
对象。timedelta
对象的字符串表示形式与其内部表示形式相似。这导致负的timedeltas 的结果有些不寻常。例如:>>> timedelta(hours=-5) datetime.timedelta(-1, 68400) >>> print(_) -1 day, 19:00:00
除了上面列出的操作,timedelta
对象支持与date
和datetime
对象相加和相减(见下文)。
支持timedelta
对象的比较,表示较小时间差的timedelta
对象被认为是较小的timedelta。为了阻止混合类型之间的比较回退到默认的以对象地址进行的比较,当将timedelta
对象与不同类型的对象进行比较时,会引发TypeError
除非比较是==
或!=
。后一种情况分别返回False
或True
。
timedelta
对象是可哈希的(可用作字典键),支持高效的pickling,在布尔上下文中,timedelta
当且仅当它不等于timedelta(0)
时才为真。
实例方法:
-
timedelta.
total_seconds
()¶ 返回时间差中包含的总的秒数。等同于
td / timedelta(seconds=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(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
对象¶
date
对象表示理想化日历中的日期(年、月和日),即当前公历日历在两个方向上无限延伸。第一年的一月一日叫做第一天,第一年的一月二日叫做第二天,以此类推。这符合Dershowitz 和Reingold 的《历法计算》一书中关于公历的定义,它是所有历法计算的基础。公历和其它许多历法系统的转换可以参阅此书。
- class
datetime.
date
(year, month, day)¶ 所有的参数都是必须的。参数可以是以下范围内的整数:
MINYEAR 年 MAXYEAR t0 >
1 月 12 t0 >
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()
返回的时间戳。如果时间戳超出平台Clocaltime()
函数支持的值的范围则引发OverflowError
,如果localtime()
失败则引发OSError
。通常限制年份在1970 到 2038之间。请注意,在时间戳中包含闰秒的非POSIX系统上,fromtimestamp()
会忽略闰秒。在版本3.3中更改:如果时间戳超出平台C
localtime ()
函数支持的值范围,则引发OverflowError
而不是ValueError
。在localtime()
失败时引发OSError
而不是ValueError
- classmethod
date.
fromordinal
(ordinal)¶ 返回对应于公历序数的日期,其中第一年的一月一日为序数1。如果不满足
1 <= ordinal <= date.max.toordinal()
,则引发ValueError
。对于任何日期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 之间,包括 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),因为-timedelta在单独的情况下可能会溢出,而date1 - 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
对象都被视为真。
实例方法:
-
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()
的返回值。Hours、minutes和seconds为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.
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 year, ISO week number, ISO weekday)。
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'
。在原生的C函数ctime()
(time.ctime()
调用它,但是date.ctime()
不调用它)遵守C标准的平台上,d.ctime()
等效于time.ctime(time.mktime(d.timetuple()))
。
-
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
对象¶
datetime
对象是一个包含date
对象和time
对象所有信息的单个对象。类似date
对象,datetime
假定当前公历日历在两个方向上延伸;类似time对象,datetime
假设每天有精确的3600*24秒。
构造函数:
- class
datetime.
datetime
(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)¶ year, month 和 day 参数是必须的。tzinfo可以是
None
或tzinfo
子类的实例。其余的参数可以是以下范围内的整数:MINYEAR 年 MAXYEAR t0 >
1 月 12 t0 >
1 <= day <= number of days in the given month and year
0 小时 24
0 分钟 60
0 秒 60
0 微秒 1000000
如果给出了这些范围之外的参数,则会引发
ValueError
。
其它构造函数,都是类方法:
- 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的时区。在这种情况下,结果等效于tz.fromutc(datetime.utcnow().replace(tzinfo=tz))
。另请参见today()
、utcnow()
。
- classmethod
datetime.
utcnow
()¶ 返回当前UTC日期和时间,其中
tzinfo
为None
。这类似now()
,但返回当前UTC日期和时间,作为一个naive的datetime
对象。可以通过调用datetime.now(timezone.utc)
来得到aware的当前UTC datetime。另请参见now()
。
- classmethod
datetime.
fromtimestamp
(timestamp, tz=None)¶ 返回与POSIX时间戳对应的本地日期和时间,例如
time.time()
返回的时间戳。如果可选参数tz为None
或未指定,则时间戳将转换为平台的本地日期和时间,返回的datetime
对象是naive的。如果tz不是
None
,则必须是tzinfo
子类的实例,此时时间戳将转换为tz的时区。在这种情况下,结果等效于tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))
。如果时间戳超出平台C
localtime()
或gmtime()
函数支持的值的范围,则fromtimestamp()
可能引发OverflowError
;如果localtime()
或gmtime()
函数失败,则引发OSError
。常见的做法是限制年份在1970和2038之间。请注意,在时间戳中包含闰秒的非POSIX系统上,fromtimestamp()
会忽略闰秒,这可能使得两个相差1秒的时间戳产生相同的datetime
对象。另请参见utcfromtimestamp()
。在版本3.3中更改:如果时间戳超出平台C
localtime ()
或gmtime()
函数支持的值范围,则引发OverflowError
而不是ValueError
。在localtime()
或gmtime()
失败时引发OSError
而不是ValueError
- classmethod
datetime.
utcfromtimestamp
(timestamp)¶ 返回与POSIX时间戳对应的UTC
datetime
,其中tzinfo
为None
。如果时间戳超出平台Cgmtime()
函数支持的值的范围,则它可能引发OverflowError
;如果gmtime()
函数失败,则引发OSError
。常见的做法是限制年份在1970和2038之间。要获取aware的
datetime
对象,请调用fromtimestamp()
:datetime.fromtimestamp(timestamp, timezone.utc)
在POSIX兼容平台上,它等效于以下表达式:
datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=timestamp)
但后者公式始终支持全部的年份范围:
MINYEAR
和MAXYEAR
之间。在版本3.3中更改:如果时间戳超出平台C
gmtime()
函数支持的值范围,则引发OverflowError
而不是ValueError
。在gmtime()
失败时引发OSError
而不是ValueError
- classmethod
datetime.
fromordinal
(ordinal)¶ 返回对应于普通公历的序数的
datetime
,其中第1年的1月1日为序数1。如果不满足1 <= ordinal <= datetime.max.toordinal()
,则引发ValueError
。结果的hour、minute、second和microsecond都是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
,根据format进行解析。这相当于datetime(*(time.strptime(date_string, format)[0:6]))
如果time.strptime()
无法解析date_string和format,或者如果返回的值不是时间元组,则会引发ValueError
。有关格式化指令的完整列表,请参见strftime()和strptime()的行为。
类属性:
实例属性(只读):
-
datetime.
month
¶ 在 1 到 12 之间,包括 1 和 12。
-
datetime.
day
¶ 在 1 到给出的年份和月份之间的天数。
-
datetime.
hour
¶ 在
range(24)
之间。
-
datetime.
minute
¶ 在
range(60)
之间。
-
datetime.
second
¶ 在
range(60)
之间。
-
datetime.
microsecond
¶ 在
range(1000000)
之间。
支持的操作:
操作 | 结果 |
---|---|
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则向后移动。结果具有与输入datetime相同的tzinfo
属性,并且之后datetime2 - datetime1 == timedelta。如果datetime2.year小于MINYEAR
或大于MAXYEAR
,则会引发OverflowError
。请注意,即使输入是aware对象,也不会执行时区调整。计算datetime2,使datetime2 + timedelta == datetime1。与加法一样,结果具有与输入日期时间相同的
tzinfo
属性,即使输入是aware的,也不执行时区调整。这不完全等同于 datetime1 + (-timedelta),因为单独的-timedelta可能会溢出,而在此情况下datetime1 - timedelta不会。只有当两个操作数都是naive的或者两者都是aware的时,才定义从
datetime
减去一个datetime
。如果一个是aware的而另一个是naive的,则会引发TypeError
。如果两者都是naive的,或者两者都是aware的且具有相同的
tzinfo
属性,则会忽略tzinfo
属性,结果是一个timedelta
对象t,使得datetime2 + t == datetime1
。在这种情况下不进行时区调整。如果两者都是aware的且具有不同的
tzinfo
属性,则a-b
表现得好像a和b被首先转换成naive的UTC时间。结果是(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset())
,除非具体的实现永远不会溢出。当datetime1在时间上位于datetime2 之前,则认为datetime1小于datetime2。
如果一个比较数据是naive的,而另一个是aware的,则尝试进行顺序比较时会产生
TypeError
。对于相等性比较,naive实例永远不等于aware实例。如果两个比较数都是aware的并且具有相同的
tzinfo
属性,则忽略共同的tzinfo
属性,并比较基本的时间数据。如果两个比较数都是aware并且具有不同的tzinfo
属性,则首先通过减去它们的UTC偏移(从self.utcoffset()
获得)来调整比较数。
datetime
对象可以用作字典的键。在布尔上下文中,所有datetime
对象都被视为真。
实例方法:
-
datetime.
replace
([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]])¶ 返回具有相同属性的 datetime,但通过任何关键字参数指定新值的那些属性除外。 请注意,可以指定
tzinfo=None
来从aware的datetime创建一个naive的datetime,而不需对date和time数据进行转换。
-
datetime.
astimezone
(tz=None)¶ 返回带有新
tzinfo
属性tz的datetime
对象,调整日期和时间数据使结果与self 的UTC时间相同,但为tz的本地时间。如果提供,tz必须是
tzinfo
子类的实例,并且其utcoffset()
和dst()
方法不得返回None
。self必须是aware的(self.tzinfo
不能是None
,以及self.utcoffset()
不能返回None
)。如果不带参数调用(或
tz=None
),则假定使用系统本地时区。转换后的datetime实例的.tzinfo
属性将设置为timezone
的实例,其带有从操作系统获取的时区名称和偏移量。如果
self.tzinfo
为tz,则self.astimezone(tz)
等于self:日期调整和时间数据不会调整。否则结果是时区tz中的本地时间,表示与self相同的UTC时间:astz = dt.astimezone(tz)
之后,astz - astz.utcoffset()
通常具有与dt - dt.utcoffset()
相同的日期和时间数据。类tzinfo
的讨论解释了无法实现的在夏令时转换边界的情况(仅当tz同时建模标准时和夏令时的时候才出现问题)。如果你只想在不调整日期和时间数据的情况下将时区对象tz附加到datetimedt,请使用
dt.replace(tzinfo=tz)
。如果你只想从aware的datetime dt中删除时区对象而不转换日期和时间数据,请使用dt.replace(tzinfo=None)
。请注意,可以在
tzinfo
子类中覆盖默认的tzinfo.fromutc()
方法,以影响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现在可以省略。
-
datetime.
utcoffset
()¶ 如果
tzinfo
为None
,则返回None
,否则返回self.tzinfo.utcoffset(self)
;如果后者未返回None
或表示小于一天的整数分钟的timedelta
对象,则引发一个异常。
-
datetime.
dst
()¶ 如果
tzinfo
为None
,则返回None
,否则返回self.tzinfo.dst(self)
;如果后者未返回None
或表示小于一天的整数分钟的timedelta
对象,则引发一个异常。
-
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
天。根据dst()
方法设置结果的tm_isdst
标志:如果tzinfo
为None
或dst()
返回None
,则tm_isdst
设置为-1
;如果dst()
返回非零值,tm_isdst
设置为1
;否则tm_isdst
设置为0
。
-
datetime.
utctimetuple
()¶ 如果
datetime
实例d是naive的,它等同于d.timetuple()
,但是无论d.dst()
返回什么,tm_isdst
都被强制设置为0。对于UTC时间DST始终不会生效。如果d是aware的,则通过减去
d.utcoffset()
归一化d,并返回归一化的时间time.struct_time
。tm_isdst
被强制为0。请注意,如果d.year是MINYEAR
或MAXYEAR
且UTC调整溢出超过一年的边界,则可能会引发OverflowError
。
-
datetime.
toordinal
()¶ 返回日期的公历序数。等同于
self.date().toordinal()
。
-
datetime.
timestamp
()¶ 返回对应于
datetime
实例的POSIX时间戳。返回值类似于time.time()
返回的float
。Naive的
datetime
实例假设表示本地时间,并且此方法依赖于平台Cmktime()
函数来执行转换。由于在许多平台上,datetime
支持的值范围比mktime()
的范围更广,因此此方法可能会在很远的过去或很远的未来时间引发OverflowError
。对于aware的
datetime
实例,返回值计算为:(dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()
版本3.3中的新功能。
注意
没有任何方法直接从表示UTC时间的一个naive的
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 year, ISO week number, ISO weekday)。等同于
self.date().isocalendar()
。
-
datetime.
isoformat
(sep='T')¶ 返回以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.
ctime
()¶ 返回一个表示日期和时间的字符串,例如
datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'
。在原生的C函数ctime()
(time.ctime()
调用它,但是datetime.ctime()
不调用它)遵守C标准的平台上,d.ctime()
等效于time.ctime(time.mktime(d.timetuple()))
。
-
datetime.
strftime
(format)¶ 返回一个表示日期和时间的字符串,由显式的格式字符串控制。有关格式化指令的完整列表,请参见strftime()和strptime()的行为。
-
datetime.
__format__
(format)¶ 与
datetime.strftime()
相同。这使得可以在使用str.format()
时为datetime
对象指定格式字符串。有关格式化指令的完整列表,请参见strftime()和strptime()的行为。
使用datetime 对象的例子:
>>> 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 的datetime:
>>> 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. time
对象¶
Time对象表示一天中的(本地)时间,独立于任何特定的日子,并且可以通过tzinfo
对象进行调整。
- class
datetime.
time
(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)¶ 所有参数都是可选的。tzinfo可以是
None
或tzinfo
子类的实例。其余的参数可以是以下范围内的整数:0 小时 24
0 分钟 60
0 秒 60
0 微秒 1000000
。
如果给出了这些范围之外的参数,则会引发
ValueError
。所有默认值为0
,除了tzinfo默认为None
。
类属性:
实例属性(只读):
-
time.
hour
¶ 在
range(24)
之间。
-
time.
minute
¶ 在
range(60)
之间。
-
time.
second
¶ 在
range(60)
之间。
-
time.
microsecond
¶ 在
range(1000000)
之间。
支持的操作:
time
和time
比较,其中如果a在时间上位于b之前,则认为a小于b。如果一个比较数据是naive的,而另一个是aware的,则尝试进行顺序比较时会产生TypeError
。对于相等性比较,naive实例永远不等于aware实例。如果两个比较数都是aware的并且具有相同的
tzinfo
属性,则忽略共同的tzinfo
属性,并比较基本的times数据。如果两个比较数都是aware并且具有不同的tzinfo
属性,则首先通过减去它们的UTC偏移(从self.utcoffset()
获得)来调整比较数。为了阻止混合类型之间的比较回退到默认的以对象地址进行的比较,当将time
对象与不同类型的对象进行比较时,会引发TypeError
除非比较是==
或!=
。后一种情况分别返回False
或True
。哈希,用作字典的键
高效的pickling
在布尔上下文中,time
对象始终被视为真。
在3.5版本中已更改:在Python 3.5之前,如果某个time
对象表示UTC的午夜,则将其视为假。这个行为被认为是晦涩的且容易出错的,已在Python 3.5中删除。有关详细信息,请参见issue 13936。
实例方法:
-
time.
replace
([hour[, minute[, second[, microsecond[, tzinfo]]]]])¶ 返回具有相同值的
time
,但通过任何关键字参数指定新值的那些属性除外。请注意,可以指定tzinfo=None
来从aware的time
创建一个naive的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:MM。
-
time.
__str__
()¶ 对于时间t,
str(t)
等同于t.isoformat()
。
-
time.
strftime
(format)¶ 返回一个表示time的字符串,由显式的格式字符串控制。有关格式化指令的完整列表,请参见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.utcoffset(None)
;如果后者未返回None
或表示小于一天的整数分钟的timedelta
对象,则引发一个异常。
例子:
>>> from datetime import time, tzinfo
>>> 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. tzinfo
对象¶
- class
datetime.
tzinfo
¶ 这是一个抽象的基类,意味着这个类不应该直接实例化。你需要派生一个具体的子类,并且(至少)提供你使用的
datetime
方法所需的标准tzinfo
方法的实现。datetime
模块提供tzinfo
的一个简单的具体子类timezone
,它可以表示与UTC有固定偏移的时区,如UTC本身或北美EST和EDT。可以将
tzinfo
(的具体子类)的实例传递给datetime
和time
对象的构造函数。后面的对象将它们的属性视为在本地时间,并且tzinfo
对象支持显示本地时间与UTC的偏移量、时区的名称和DST偏移量,所有这些都相对于传递给它们的日期或时间对象。用于pickling的特殊要求:
tzinfo
子类必须有一个可以无参数调用的__init__()
方法,否则它可以被pickled,但可能不能再次unpickled。这是一个在将来可能放松的技术要求。tzinfo
的具体子类可能需要实现以下方法。需要哪些方法取决于对aware的datetime
对象的使用。如果有疑问,请实施所有这些。
-
tzinfo.
utcoffset
(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
(dt)¶ 如果DST信息未知,则返回夏令时(DST)调整(以UTC以东为单位),或者
None
。如果DST不起作用,则返回timedelta(0)
。如果DST有效,则将偏移返回为timedelta
对象(有关详细信息,请参阅utcoffset()
)。请注意,DST偏移(如果适用)已添加到utcoffset()
返回的UTC偏移,因此除非你感兴趣,否则不需要单独查阅dst()
获得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
(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
时,由类设计器决定最佳响应。例如,如果类想要说time对象不参与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
类的示例:
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开始(“start行)时,本地挂钟从1:59走到3:00。格式2:MM的挂钟时间在当天没有任何意义,因此在DST开始的时候,astimezone(Eastern)
不会产生结果hour == 2
。为了使astimezone()
作出此保证,tzinfo.dst()
方法必须考虑在夏令时“缺少的小时”(东部时间2:MM)。
当DST结束(“end”行)时,有一个可能更糟糕的问题:有一个小时不能在本地墙上时间明确拼写:白天的最后一个小时。在东部,这是在日间时间结束时5:MM UTC形式的间。本地挂钟再次从1:59(白昼时间)回到1:00(标准时间)。Local times of the form 1:MM are ambiguous. astimezone()
模拟本地时钟的行为,通过将两个相邻的UTC小时映射到相同的当地小时。在Eastern这个示例中,5:MM形式和6:MM形式的UTC时间在转换到Eastern时都映射到1:MM。为了使astimezone()
作出此保证,tzinfo.dst()
方法必须将“重复小时”中的时间考虑为标准时间。通过在时区的标准本地时间中表示DST切换时间,这可以容易地做到,如在该示例中。
不能承受这种歧义的应用程序应避免使用混合tzinfo
子类;使用timezone
或任何其他固定偏移的tzinfo
子类(例如只表示EST(固定偏移-5小时)或只表示ED(T固定偏移-4小时)的类)。
另请参阅
- pytz
标准库有
timezone
类来处理UTC任意固定偏移和timezone.utc
作为UTC时区实例。pytz库将IANA时区数据库(也称为Olson数据库)带到Python,建议使用它。
- IANA时区数据库
- 时区数据库(通常称为tz或zoneinfo)包含代表世界各地许多代表性位置的本地时间历史的代码和数据。它定期更新,以反映政治机构对时区边界、UTC偏移和夏令时规则所做的更改。
8.1.7. timezone
对象¶
timezone
类是tzinfo
的子类,其每个实例表示由与UTC的固定偏移量定义的时区。请注意,此类的对象不能用于在一年中不同日期使用不同偏移量的位置,或者对民用时间进行历史更改的位置来表示时区信息。
- class
datetime.
timezone
(offset[, name])¶ offset参数必须指定为表示本地时间和UTC之间差异的
timedelta
对象。它必须严格在-timedelta(hours=24)
和timedelta(hours=24)
之间并表示整分钟数,否则引发ValueError
。name参数是可选的。如果指定,它必须是用作
tzname(dt)
方法返回的值的字符串。否则,tzname(dt)
返回字符串'UTCsHH:MM',其中s是offset的符号,HH和MM分别是offset.hours
和offset.minutes
。版本3.2中的新功能。
-
timezone.
tzname
(dt)¶ 返回在构建
timezone
实例时指定的固定值或字符串'UTCsHH:MM',其中s是offset的符号,HH和MM分别是offset.hours
和offset.minutes
。
-
timezone.
dst
(dt)¶ 始终返回
None
。
类属性:
-
timezone.
utc
¶ UTC时区,
timezone(timedelta(0))
。
8.1.8. 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]))
。
对于time
对象,不应使用年、月和日的格式代码,因为时间对象没有此类值。如果仍然使用它们,则用1900
代替年份,1
代替月份和日期。
对于date
对象,不应使用小时、分钟、秒和微秒的格式代码,因为date
对象没有此类值。如果仍然使用它们,则用0
代替它们。
支持的全套格式代码因平台而异,因为Python调用平台C库的strftime()
函数,平台的变化是常见的。若要查看你的平台上支持的完整格式码集,请参阅strftime(3)的文档。
下面列出了C标准(1989版)要求的所有格式码,它们在所有具有标准C实现的平台上都可以工作。注意1999版的C标准添加了额外的格式码。
指令 | 含义 | 例子 | 备注 |
---|---|---|---|
%a | 星期名称的区域性简写。 | Sun, Mon, ..., Sat (en_US); So, Mo, ..., Sa (de_DE) | (1) |
%A | 星期名称的区域性全称。 | Sunday, Monday, ..., Saturday (en_US); Sonntag, Montag, ..., Samstag (de_DE) | (1) |
%w | 数字形式的星期,0表示星期日,6表示星期六。 | 0, 1, ..., 6 | |
%d | 以0填充的十进制数字表示的月份中的日期。 | 01, 02, ..., 31 | |
%b | 月份名称的区域性简写。 | Jan,Feb,...,Dec(en_US); Jan,Feb,...,Dez(de_DE) | (1) |
%B | 月份名称的区域性全称。 | January, February, ..., December (en_US); Januar,Februar,...,Dezember(de_DE) | (1) |
%m | 以0填充的十进制数表示的月份。 | 01, 02, ..., 12 | |
%y | 以0填充的十进制数表示的不带世纪的年份。 | 00, 01, ..., 99 | |
%Y | 以0填充的十进制数表示的带有世纪的年份。 | 0001, 0002, ..., 2013, 2014, ..., 9998, 9999 | (2) |
%H | 以0填充的十进制数表示的小时(24小时制)。 | 00, 01, ..., 23 | |
%I | 以0填充的十进制数表示的小时(12小时制)。 | 01, 02, ..., 12 | |
%p | AM或PM区域性设置。 | AM, PM (en_US); am, pm (de_DE) | (1),(3) |
%M | 以0填充的十进制数表示的分钟。 | 00,01,...,59 | |
%S | 以0填充的十进制数表示的秒数。 | 00,01,...,59 | (4) |
%f | 十进制数表示的微秒,左边以0填充。 | 000000,000001,...,999999 | (5) |
%z | +HHMM或-HHMM形式的UTC偏移(如果对象是naive的,则为空字符串)。 | (empty), +0000, -0400, +1030 | (6) |
%Z | 时区名称(如果对象是naive的,则为空字符串)。 | (empty), UTC, EST, CST | |
%j | 以0填充的十进制数字表示的一年中的日期。 | 001,002,...,366 | |
%U | 以0填充的十进制数字表示的一年中的第几个星期(星期天作为一个星期的第一天)。新的一年中第一个星期天之前的所有日期都被认为是在第0个星期。 | 00,01,...,53 | (7) |
%W | 以0填充的十进制数字表示的一年中的第几个星期(星期一作为一个星期的第一天)。 新的一年中第一个星期一之前的所有日期都被认为是在第0个星期。 | 00,01,...,53 | (7) |
%c | 适合区域设置的日期和时间表示。 | Tue Aug 16 21:30:00 1988(en_US); Di 16 Aug 21:30:00 1988(de_DE) | (1) |
%x | 适合区域的日期表示。 | 08/16/88(无); 08/16/1988(en_US); 16.08.1988(de_DE) | (1) |
%X | 适合区域的时间表示。 | 21:30:00(zh_US); 21:30:00(de_DE) | (1) |
%% | 字面值'%' 字符。 | % |
注意:
因为格式取决于当前的区域设置,在做出关于输出值的假设时应该小心。字段顺序将有所不同(例如,“月/日/年”和“日/月/年”),输出可能包含使用区域设置的默认编码进行编码的Unicode字符(例如,如果当前区域设置为
ja_JP
,默认编码可以是eucJP
、SJIS
或utf-8
中的任何一个;使用locale.getlocale()
以确定当前区域设置的编码)。strptime()
方法可以解析完整稍微[1,9999]范围内的年份,但 < 1000的年份必须使用0填充到4位数。在版本3.2中更改:在以前的版本中,
strftime()
方法仅限于>= 1900的年份。在版本3.3中更改:在版本3.2中,
strftime()
方法仅限于>= 1000的年份。当与
strptime()
方法一起使用时,只有在使用%I
指令解析小时的时候,%p
指令才会影响输出。当与
strptime()
方法一起使用时,%f
指令接受一到六个数字,并在右边以零填充。%f
是C标准中的一组格式字符的扩展(但是在datetime对象中单独实现,因此始终可用)。对于naive对象,
%z
和%Z
格式代码将替换为空字符串。对于aware对象:
%z
utcoffset()
被转换为+HHMM或-HHMM形式的5个字符的字符串,其中HH是给出UTC偏移小时数的2位字符串,MM是给出UTC偏移分钟数的2位字符串。例如,如果utcoffset()
返回timedelta(hours=-3, minutes=-30)
,那么%z
替换为字符串'-0330'
。%Z
如果
tzname()
返回None
,则以空字符串替换%Z
。否则,%Z
被替换为返回值,它必须是字符串。
与
strptime()
方法一起使用时,%U
和%W
仅在指定星期和年份时使用。
脚注
[1] | 如果,也就是说,我们忽略相对论的影响 |