Python 时间库:如何使用 strptime 和 strftime 保存 dst
Python time library: how do I preserve dst with strptime and strftime
我需要以可读格式存储时间戳,稍后我需要将其转换为纪元以供比较。
我试过这样做:
import time
format = '%Y %m %d %H:%M:%S +0000'
timestamp1 = time.strftime(format,time.gmtime()) # '2016 03 25 04:06:22 +0000'
t1 = time.strptime(timestamp1, format) # time.struct_time(..., tm_isdst=-1)
time.sleep(1)
epoch_now = time.mktime(time.gmtime())
epoch_t1 = time.mktime(t1)
print "Delta: %s" % (epoch_now - epoch_t1)
运行 这个,我得到的不是 1 秒的增量,而是 3601(1 小时 1 秒),始终如一。
进一步调查,似乎当我只做 time.gmtime() 时,结构有 tm_isdst=0,而从 timestamp1 字符串转换的结构 t1 有 tm_isdst=- 1.
如何确保 isdst 保留为 0。我认为这可能是这里的问题。
或者是否有更好的方法以人类可读格式 (UTC) 记录时间,并且能够正确转换回纪元以计算时差?
更新:
昨晚做了更多研究后,我转而使用 datetime,因为它在 datetime 对象中保留了更多信息,下面的 albertoql 回答证实了这一点。
这是我现在拥有的:
from datetime import datetime
format = '%Y-%m-%d %H:%M:%S.%f +0000' # +0000 is optional; only for user to see it's UTC
d1 = datetime.utcnow()
timestamp1 = d1.strftime(format)
d1a = datetime.strptime(timestamp1, format)
time.sleep(1)
d2 = datetime.utcnow()
print "Delta: %s" % (d2 - d1a).seconds
我选择不加tz来保留它simple/shorter;我仍然可以这样 strptime。
下面,首先是对问题的解释,然后是两种可能的解决方案,一种使用 time
, another using datetime
。
问题解释
问题在于 OP 在问题中所做的观察:tm_isdst=-1
。 tm_isdst
是一个标志,用于确定夏令时是否有效(有关详细信息,请参阅 https://docs.python.org/2/library/time.html#time.struct_time)。
具体来说,给定OP中时间的字符串格式(符合RFC 2822 Internet email standard), [time.strptime
]4 does not store the information about the timezone, namely +0000
. Thus, when the struct_time
的是根据字符串中的信息重新创建的,tm_isdst=-1
,即未知。猜测如何填写计算时的信息是基于本地系统的。例如,如果系统指的是北美,那里实行夏令时,则设置 tm_isdst
。
time
的解决方案
如果你只想使用time
package, then, the easiest way to parse directly the information is to specify that the time is in UTC, and thus adding %Z
to the format. Note that time
does not provide a way to store the information about the timezone in struct_time
. As a result, it does not print the actual time zone associated with the time saved in the variable. The time zone is retrieved from the system. Therefore, it is not possible to directly use the same format for time.strftime
。写入和读取字符串的代码部分如下所示:
format = '%Y %m %d %H:%M:%S UTC'
format2 = '%Y %m %d %H:%M:%S %Z'
timestamp1 = time.strftime(format, time.gmtime())
t1 = time.strptime(timestamp1, format2)
datetime
的解决方案
另一种解决方案涉及使用 datetime
and dateutil
包,它直接支持时区,代码可以是(假设需要保留时区信息):
from datetime import datetime
from dateutil import tz, parser
import time
time_format = '%Y %m %d %H:%M:%S %z'
utc_zone = tz.gettz('UTC')
utc_time1 = datetime.utcnow()
utc_time1 = utc_time1.replace(tzinfo=utc_zone)
utc_time1_string = utc_time1.strftime(time_format)
utc_time1 = parser.parse(utc_time1_string)
time.sleep(1)
utc_time2 = datetime.utcnow()
utc_time2 = utc_time2.replace(tzinfo=utc_zone)
print "Delta: %s" % (utc_time2 - utc_time1).total_seconds()
需要注意的几个方面:
调用 utcnow
后,未设置时区,因为它是一个简单的 UTC 日期时间。如果不需要有关UTC的信息,可以将两次设置时区的行都删除,结果是一样的,因为没有猜测DST。
无法使用 datetime.strptime
,因为 %z
未正确解析。如果字符串包含有关时区的信息,则应使用 parser
。
可以直接对 datetime
的两个实例进行差分并将得到的差值转换为秒数。
如果需要获取自纪元以来的秒数,则应进行显式计算,因为在 datetime
(在回答时间)。在代码下方,例如 utc_time2
:
epoch_time = datetime(1970,1,1)
epoch2 = (utc_time2 - epoch_time).total_seconds()
datetime.resolution
,即两个不相等的datetime
对象之间的最小可能差异。这导致取决于分辨率的差异。
我需要以可读格式存储时间戳,稍后我需要将其转换为纪元以供比较。
我试过这样做:
import time
format = '%Y %m %d %H:%M:%S +0000'
timestamp1 = time.strftime(format,time.gmtime()) # '2016 03 25 04:06:22 +0000'
t1 = time.strptime(timestamp1, format) # time.struct_time(..., tm_isdst=-1)
time.sleep(1)
epoch_now = time.mktime(time.gmtime())
epoch_t1 = time.mktime(t1)
print "Delta: %s" % (epoch_now - epoch_t1)
运行 这个,我得到的不是 1 秒的增量,而是 3601(1 小时 1 秒),始终如一。
进一步调查,似乎当我只做 time.gmtime() 时,结构有 tm_isdst=0,而从 timestamp1 字符串转换的结构 t1 有 tm_isdst=- 1.
如何确保 isdst 保留为 0。我认为这可能是这里的问题。
或者是否有更好的方法以人类可读格式 (UTC) 记录时间,并且能够正确转换回纪元以计算时差?
更新: 昨晚做了更多研究后,我转而使用 datetime,因为它在 datetime 对象中保留了更多信息,下面的 albertoql 回答证实了这一点。
这是我现在拥有的:
from datetime import datetime
format = '%Y-%m-%d %H:%M:%S.%f +0000' # +0000 is optional; only for user to see it's UTC
d1 = datetime.utcnow()
timestamp1 = d1.strftime(format)
d1a = datetime.strptime(timestamp1, format)
time.sleep(1)
d2 = datetime.utcnow()
print "Delta: %s" % (d2 - d1a).seconds
我选择不加tz来保留它simple/shorter;我仍然可以这样 strptime。
下面,首先是对问题的解释,然后是两种可能的解决方案,一种使用 time
, another using datetime
。
问题解释
问题在于 OP 在问题中所做的观察:tm_isdst=-1
。 tm_isdst
是一个标志,用于确定夏令时是否有效(有关详细信息,请参阅 https://docs.python.org/2/library/time.html#time.struct_time)。
具体来说,给定OP中时间的字符串格式(符合RFC 2822 Internet email standard), [time.strptime
]4 does not store the information about the timezone, namely +0000
. Thus, when the struct_time
的是根据字符串中的信息重新创建的,tm_isdst=-1
,即未知。猜测如何填写计算时的信息是基于本地系统的。例如,如果系统指的是北美,那里实行夏令时,则设置 tm_isdst
。
time
的解决方案
如果你只想使用time
package, then, the easiest way to parse directly the information is to specify that the time is in UTC, and thus adding %Z
to the format. Note that time
does not provide a way to store the information about the timezone in struct_time
. As a result, it does not print the actual time zone associated with the time saved in the variable. The time zone is retrieved from the system. Therefore, it is not possible to directly use the same format for time.strftime
。写入和读取字符串的代码部分如下所示:
format = '%Y %m %d %H:%M:%S UTC'
format2 = '%Y %m %d %H:%M:%S %Z'
timestamp1 = time.strftime(format, time.gmtime())
t1 = time.strptime(timestamp1, format2)
datetime
的解决方案
另一种解决方案涉及使用 datetime
and dateutil
包,它直接支持时区,代码可以是(假设需要保留时区信息):
from datetime import datetime
from dateutil import tz, parser
import time
time_format = '%Y %m %d %H:%M:%S %z'
utc_zone = tz.gettz('UTC')
utc_time1 = datetime.utcnow()
utc_time1 = utc_time1.replace(tzinfo=utc_zone)
utc_time1_string = utc_time1.strftime(time_format)
utc_time1 = parser.parse(utc_time1_string)
time.sleep(1)
utc_time2 = datetime.utcnow()
utc_time2 = utc_time2.replace(tzinfo=utc_zone)
print "Delta: %s" % (utc_time2 - utc_time1).total_seconds()
需要注意的几个方面:
调用
utcnow
后,未设置时区,因为它是一个简单的 UTC 日期时间。如果不需要有关UTC的信息,可以将两次设置时区的行都删除,结果是一样的,因为没有猜测DST。无法使用
datetime.strptime
,因为%z
未正确解析。如果字符串包含有关时区的信息,则应使用parser
。可以直接对
datetime
的两个实例进行差分并将得到的差值转换为秒数。如果需要获取自纪元以来的秒数,则应进行显式计算,因为在
datetime
(在回答时间)。在代码下方,例如utc_time2
:epoch_time = datetime(1970,1,1) epoch2 = (utc_time2 - epoch_time).total_seconds()
datetime.resolution
,即两个不相等的datetime
对象之间的最小可能差异。这导致取决于分辨率的差异。