Python - calendar.timegm() 与 time.mktime() 的区别
我好像很难理解这个问题。
calendar.timegm()
和time.mktime()
有什么区别呢?
假设我有一个没有时区信息的datetime.datetime
对象,这两个函数的输出不应该是一样的吗?它们不都是计算从“纪元”(也就是1970年1月1日)到传入日期之间的秒数吗?而且因为传入的日期没有时区信息,所以这个秒数不应该是相同的吗?
>>> import calendar
>>> import time
>>> import datetime
>>> d = datetime.datetime(2010, 10, 10)
>>> calendar.timegm(d.timetuple())
1286668800
>>> time.mktime(d.timetuple())
1286640000.0
>>>
3 个回答
让我们来看下面的例子,
>>> import datetime
>>> import time
>>> import calendar
>>> utc_time_now = datetime.datetime.utcnow()
>>> utc_time_now
datetime.datetime(2022, 5, 21, 6, 47, 33, 929433)
>>> time.mktime(utc_time_now.timetuple())
1653095853.0
>>> calendar.timegm(utc_time_now.timetuple())
1653115653
>>> time.tzname
('IST', 'IST')
>>> time.strftime("%z", time.gmtime())
'+0530'
>>> (1653115653-1653095853)
19800
在我们开始解释之前,请注意,'datetime.datetime.utcnow()' 返回的是一个日期时间对象,这个对象是“天真的”,也就是说它没有关于你本地时区的信息。
time.mktime()
把这个函数应用到一个日期时间对象上时,会考虑到“时区”。
所以根据上面的例子,当你把时间 '2022-05-21 06:47:33' 提供给 time.gmtime() 时,它假设这个时间实际上不是在 UTC,而是在你的本地时区(在我这里是 'IST')。
在我的情况下,时区是 'IST',比 UTC 快 5小时30分钟(+05:30)。所以为了返回 UTC 时区的时间,它会从日期时间对象中减去 +05:30(19800秒),在计算时间戳时就这样处理。
因此,它返回的时间戳是 (1653095853.0),比原始的 UTC 纪元秒(1653115653)少了 19800 秒。
注意:如果你的时区是负的(比如 -05:30),它会在最终的纪元计算中加上 19800 秒。因此你会发现 time.gmtime() 返回的时间戳比 UTC 纪元时间戳大 19800 秒。
calendar.timegm()
这个函数返回对应的 Unix 时间戳值,假设纪元是 1970-01-01。因此在日期时间对象上不会做额外的调整。
无论它得到什么日期时间对象的值,都会从纪元时间 '1970-01-01' 中减去,并返回经过的总秒数。
额外提示
从你的 UTC 日期时间对象中获取时间戳的毫秒数。
第一种方法:
>>> utc_time_now
datetime.datetime(2022, 5, 21, 7, 16, 34, 938547)
>>> int((calendar.timegm(utc_time_now.timetuple()) + (utc_time_now.microsecond/1e6))*1000.0)
1653117394938
第二种方法:
>>> utc_time_epoch = datetime.datetime.utcfromtimestamp(0)
>>> utc_time_epoch
datetime.datetime(1970, 1, 1, 0, 0)
>>> utc_time_now = datetime.datetime.utcnow()
>>> utc_time_now
datetime.datetime(2022, 5, 21, 7, 16, 34, 938547)
>>> elapsed_time = utc_time_now - utc_time_epoch
>>> elapsed_time
datetime.timedelta(19133, 26194, 938547)
>>> int(elapsed_time.total_seconds() * 1000.0)
1653117394938
祝你玩得愉快 :)
calendar.timegm
是用来把 UTC 时间戳转换成其他格式的,而 time.mktime
则是用来把本地时间(不是 UTC 时间)转换成其他格式的。
它们的结果相差 8 个小时,正好对应你所在的时区。
time.mktime()
这个函数假设你传入的时间元组是本地时间,而 calendar.timegm()
则假设这个时间是格林威治标准时间(GMT)或协调世界时(UTC)。因为这两个函数对时间的理解不同,所以它们返回的结果也会不同(返回的时间是从1970年1月1日开始计算的秒数,基于UTC)。
这两个值之间的差异应该等于你所在时区的时差。