1. time.time()在不同系统返回的不一定相同
一般获取时间是调用time.time(),这个是获取的是从epoch开始到现在的秒数浮点值,在大多数系统中 ( Windows 和大多数 Unix ) 它返回的是从1970年1月1日00:00:00到现在标准时区的秒数,即UTC。
- epoch 是时间开始的点,并且取决于平台。对于Unix, epoch 是1970年1月1日00:00:00(UTC)。要找出给定平台上的 epoch ,请查看
time.gmtime(0)
。
2. time.mktime()表示的是local时间
当我们通过time.strptime去构造一个struct_time,再通过time.mktime去转换成时间戳与time.time()作比较时,这个time.mktime转换出来的值会与其所在的时区相关。如下:
# 当前的 time.time() 返回的是UTC
time.gmtime(0)
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)
# 当前北京时间2021/6/8-15:50:00左右
>>> time.time() - time.mktime(time.strptime(r"2021/6/8-15:50:00", "%Y/%m/%d-%H:%M:%S"))
17.619999885559082
根据第一点我们可以知道,time.time()返回的是UTC时区的时间戳,为何我用北京时间构造的时间戳与time.time()相减会一致呢 (十几秒的误差是因为秒没有对齐)
就是因为 time.mktime 根据本地电脑的时区 (UTC + 8),将输入的时间根据本地时区调整回UTC时区,如案例即是将时间减去8小时,所以就和UTC时间重合了。
所以当服务器与客户端都用mktime去构造时间戳时,就要考虑到服务器与客户端不在同一个时区,不然会返回两个不同的时间戳。
Python提供了一个不考虑时区的时间戳构造函数,calendar.timegm()
calendar.
timegm
(tuple)一个不相关但很好用的函数,它接受一个时间元组例如 time 模块中的 gmtime() 函数的返回并返回相应的 Unix 时间戳值,假定 1970 年开始计数, POSIX 编码。实际上, time.gmtime() 和 timegm() 是彼此相反的。
其默认传入的时间就是以UTC为标准的,就不会去根据本地时区调整了。
3. 夏令时问题
这个夏令时也是个非常诡异的东西,说是为了节约能源,高纬度地区夏季太阳升起时间早,就把时间拨快一个小时,让人早点起床,不用晚上开灯;冬季反之。
如此就带来了部分地区时间会快/慢一点的问题,在Python中用time.strptime()构造的struct_time如果没有指明,用于填充任何缺失数据的默认值是 (1900, 1, 1, 0, 0, 0, 0, 1, -1)。
即表示会根据本地是否是夏令时地区自动设置,非常坑。
print(time.strptime(r"2021/6/8-15:50:00", "%Y/%m/%d-%H:%M:%S"))
time.struct_time(tm_year=2021, tm_mon=6, tm_mday=8, tm_hour=15, tm_min=50, tm_sec=0, tm_wday=1, tm_yday=159, tm_isdst=-1)
tm_wday(星期几)
tm_yday(一年中的第几天)
tm_isdst(是否是夏令时,1是,0不是,-1根据本地)
4. 参考
https://docs.python.org/zh-cn/3.8/library/time.html#time.time