首页 > 解决方案 > 将秒数添加到时间戳后,从 unix 时间戳到日期时间转换没有得到预期结果

问题描述

我正在编写一个处理 unix 时间戳和日期的程序。我有一个日期 ( 2014-10-26 00:00:00),将其转换为其时间戳,然后加上 60 乘以 60 乘以 24 秒(一天中的秒数)。

所以生成的时间戳的日期应该是2014-10-27 00:00:00. 不是, 2014-10-26 23:00:00是 这让我很生气,我无法弄清楚这背后的逻辑。我编写了一个 python 脚本,在循环中将初始日期添加 3600 秒。

输出是:

1414274400 2014-10-26 00:00:00
1414278000 2014-10-26 01:00:00
1414281600 2014-10-26 02:00:00
1414285200 2014-10-26 02:00:00    NOTE: 02:00:00 is doubled!
1414288800 2014-10-26 03:00:00
1414292400 2014-10-26 04:00:00
1414296000 2014-10-26 05:00:00
...
           2014-10-26 23:00:00

这里发生了什么?有人可以向我解释吗?

我天真的转换程序:

def ts2date(ts):
    return(datetime.datetime.fromtimestamp(ts))

标签: pythondatetimeunix-timestampdate-conversion

解决方案


我认为这个问题围绕着naive 与有意识的 datetime以及 Python 将 naive datetime 视为本地时间,即您的机器配置为使用的时区。另请参阅我在问题下的评论。为了进一步澄清,您可以将初始结果与明确设置时区(本质上是感知日期时间)时得到的结果进行对比。

from datetime import datetime, timezone
unix = [1414274400, 1414278000, 1414281600, 1414285200, 1414288800, 1414292400, 1414296000]

最初:naive datetime(Unix 时间转换为本地时间)。请注意,我机器的时区是 Europe/Berlin,它在 2014 年 10 月 26 日进行了 DST 转换。

naive = [datetime.fromtimestamp(t) for t in unix]
print(list(map(datetime.isoformat, naive)))
# ['2014-10-26T00:00:00',
#  '2014-10-26T01:00:00',
#  '2014-10-26T02:00:00',
#  '2014-10-26T02:00:00',
#  '2014-10-26T03:00:00',
#  '2014-10-26T04:00:00',
#  '2014-10-26T05:00:00']

请注意DST 转换期间 datetime 对象的fold 属性:

print(naive[2:4])
[datetime.datetime(2014, 10, 26, 2, 0),
 datetime.datetime(2014, 10, 26, 2, 0, fold=1)]

现在与本地化到机器时区的感知日期时间进行比较(我的机器使用欧洲/柏林时区,UTC 偏移量 +1/+2):

local_aware = [datetime.fromtimestamp(t).astimezone(None) for t in unix]
print(list(map(datetime.isoformat, local_aware)))
# ['2014-10-26T00:00:00+02:00',
#  '2014-10-26T01:00:00+02:00', # CEST (summer time)
#  '2014-10-26T02:00:00+02:00', # observe the DST transition!
#  '2014-10-26T02:00:00+01:00', # CET (winter time)
#  '2014-10-26T03:00:00+01:00',
#  '2014-10-26T04:00:00+01:00',
#  '2014-10-26T05:00:00+01:00']

在我看来,您可以做的最简单的事情是使用UTC

utc = [datetime.fromtimestamp(t, timezone.utc) for t in unix]
print(list(map(datetime.isoformat, utc)))
# ['2014-10-25T22:00:00+00:00',
#  '2014-10-25T23:00:00+00:00',
#  '2014-10-26T00:00:00+00:00', # no DST transitions here of course
#  '2014-10-26T01:00:00+00:00',
#  '2014-10-26T02:00:00+00:00',
#  '2014-10-26T03:00:00+00:00',
#  '2014-10-26T04:00:00+00:00']

关于您添加秒等的第一个示例 - 这是明确指定 UTC 时的样子

from datetime import datetime, timezone

s = "2014-10-26 00:00:00" # UTC
# to aware datetime object, then Unix time
t = datetime.fromisoformat(s).replace(tzinfo=timezone.utc).timestamp()
# 1414281600.0

# add 1 day and back to datetime object / string
dt = datetime.fromtimestamp(t+86400, timezone.utc)
print(repr(dt))
# datetime.datetime(2014, 10, 27, 0, 0, tzinfo=datetime.timezone.utc)
print(dt.strftime("%Y-%m-%d %H:%M:%S"))
# 2014-10-27 00:00:00

推荐阅读