Python时间戳+日期时间转换

时间:2018-03-01 22:49:13

标签: python datetime

我有一个UNIX毫秒时间戳的测试记录,因为纪元值为1459952824358

我正在使用fastavro库编写Python 2.x程序。它采用1459952824358整数UNIX毫秒时间戳并将其转换为本地日期时间值2016-04-06T09:27:04.358000。当我尝试将其转换回整数UNIX毫秒时间戳值时,我最终关闭了一个小时。我可以使用普通的Python日期时间在fastavro库之外复制这个转换问题:

import datetime
import time

raw = 1459952824358

local_dt = datetime.datetime.fromtimestamp(raw / 1000.0)
local_dt.isoformat() # '2016-04-06T09:27:04.358000'

back = int((local_dt - datetime.datetime.fromtimestamp(0)).total_seconds() * 1.0e3)
back - raw # 3600000

我可以转换为UTC日期时间并成功返回:

import datetime
import time

raw = 1459952824358

utc_dt = datetime.datetime.utcfromtimestamp(raw / 1000.0)
utc_dt.isoformat() # '2016-04-06T14:27:04.358000'

back = int((utc_dt - datetime.datetime.utcfromtimestamp(0)).total_seconds() * 1.0e3)
back - raw # 0

奇怪的是我的系统设置为CST或UTC-6,但Python产生的本地日期时间距离UTC值五个小时而不是六个。

虽然,我的特定项目需要Python 2兼容性,但我尝试使用Python 3 timestamp函数,该函数正确地返回原始时间戳值而没有小时漂移,但本地日期时间仍然奇怪地离开了5个小时。 UTC时间,即使我的系统设置为CST或UTC-6。

import datetime
import time

raw = 1459952824358

local_dt = datetime.datetime.fromtimestamp(raw / 1000.0)
local_dt.isoformat() # '2016-04-06T09:27:04.358000'

back = int(local_dt.timestamp() * 1000)
back - raw # 0

我在同一台笔记本电脑上尝试使用Java 9中的相同示例,只是为了看看它产生了什么:

import java.time.*

long raw = 1459952824358L;

Instant i = Instant.ofEpochMilli(raw)
ZonedDateTime zdtUtc = ZonedDateTime.ofInstant(i, ZoneOffset.UTC)
// UPDATE: This line was my original attempt. It was wrong because it uses the current daylight savings setting, not the one of the given date.
ZonedDateTime zdtLocal = zdtUtc.withZoneSameInstant(ZonedDateTime.now().getOffset())
// This next line will choose the current geography, but choose the daylight savings setting based on the date, which is what I expected.
ZonedDateTime zdtLocal = zdtUtc.withZoneSameInstant(ZoneId.systemDefault())

long deltaFromUtc = zdtUtc.toInstant().toEpochMilli() - raw
long deltaFromLocal = zdtLocal.toInstant().toEpochMilli() - raw

无论utc / local是什么,它都会返回确切的原始时间戳值。

更新:基本上,Python 2.x无法在没有额外库的情况下将本地日期时间值正确转换为UTC。 Python 3.x可以,并且Python 2.x有额外的库可以做到这一点,但开箱即用,它不能。

1 个答案:

答案 0 :(得分:0)

tl; dr :你的测量是关闭的,而不是日期时间:你从不同的时区进行两次比较,结果应该是时区之间的差异,而且是。

所以这就是为什么在UTC工作更好的原因:

在Python 2.7中:

使用你的原始:

>>> print datetime.datetime.utcfromtimestamp(raw/1000.0)
... print datetime.datetime.fromtimestamp(raw/1000.0)
... 
2016-04-06 14:27:04.358000
2016-04-06 07:27:04.358000

7小时不同

在夏令时之外使用修改日期:

>>> print datetime.datetime.utcfromtimestamp(1456952824)
... print datetime.datetime.fromtimestamp(1456952824)
... 
2016-03-02 21:07:04
2016-03-02 13:07:04

8小时不同

这种情况正在发生,因为当地时间的raw0位于不同的时区(夏令时与标准时间):

>>> print datetime.datetime.utcfromtimestamp(raw/1000.0)
... print datetime.datetime.fromtimestamp(raw/1000.0)
... 
2016-04-06 14:27:04.358000
2016-04-06 07:27:04.358000

>>> print datetime.datetime.utcfromtimestamp(0)
... print datetime.datetime.fromtimestamp(0)
...
1970-01-01 00:00:00
1969-12-31 16:00:00

如果坚持使用utc,没问题。

  

但是本地日期时间仍然比UTC时间短5小时,   即使我的系统设置为CST或UTC-6。

因为在raw日期,您的当地时间将是CDT(-5):

user@TS-E31:~$ date --date @1459952824
Wed Apr  6 07:27:04 PDT 2016
user@TS-E31:~$ date --date @0
Wed Dec 31 16:00:00 PST 1969