Python 3:到datetime的时间戳:这个额外的小时来自哪里?

时间:2010-04-05 23:52:55

标签: datetime python-3.x

我正在使用以下功能:

# The epoch used in the datetime API.
EPOCH = datetime.datetime.fromtimestamp(0)

def timedelta_to_seconds(delta):
    seconds = (delta.microseconds * 1e6) + delta.seconds + (delta.days * 86400)
    seconds = abs(seconds)

    return seconds

def datetime_to_timestamp(date, epoch=EPOCH):
    # Ensure we deal with `datetime`s.
    date = datetime.datetime.fromordinal(date.toordinal())
    epoch = datetime.datetime.fromordinal(epoch.toordinal())

    timedelta = date - epoch
    timestamp = timedelta_to_seconds(timedelta)

    return timestamp

def timestamp_to_datetime(timestamp, epoch=EPOCH):
    # Ensure we deal with a `datetime`.
    epoch = datetime.datetime.fromordinal(epoch.toordinal())

    epoch_difference = timedelta_to_seconds(epoch - EPOCH)
    adjusted_timestamp = timestamp - epoch_difference

    date = datetime.datetime.fromtimestamp(adjusted_timestamp)

    return date

使用传递的代码:

twenty = datetime.datetime(2010, 4, 4)

print(twenty)
print(datetime_to_timestamp(twenty))
print(timestamp_to_datetime(datetime_to_timestamp(twenty)))

得到以下结果:

2010-04-04 00:00:00
1270339200.0
2010-04-04 01:00:00

出于某种原因,我在最后一次通话中添加了额外的小时,尽管我的代码已经看到,没有任何缺陷。

这个额外的小时来自哪里?

2 个答案:

答案 0 :(得分:4)

# Ensure we deal with `datetime`s.
date = datetime.datetime.fromordinal(date.toordinal())

(这完全切断了时间,因为'序数'只是一天的数字。这是你的意思吗?我怀疑不是。)

无论如何,正如Michael所说,datetime.fromtimestamp为您提供了一个天真的日期时间,对应于该POSIX(UTC)时间戳的本地时间。所以当你打电话时 -

date = datetime.datetime.fromtimestamp(adjusted_timestamp)

您将获得代表2010-04-04T00:00:00的POSIX时间戳的本地时间,当然在BST中提前一小时。这不会在返回方向发生,因为您的纪元是在1月,当时BST没有生效。 (但是如果你不在英国,你的EPOCH也会完全关闭。)

您应该将datetime.fromtimestamp的使用替换为datetime.utcfromtimestamp

令人遗憾的是,datetime延续了在当地时间保持时间的可怕time传统。称他们'天真'并带走DST旗帜只会让他们变得更糟。就个人而言,我无法使用datetime,更喜欢所有内容的整数UTC时间戳(仅转换为本地时区进行格式化)。

答案 1 :(得分:1)

根据您的个人资料,您在英国。这意味着由于DST,您目前正在使用UTC + 1。

如果我在Python 2.6上使用你的时间戳并通过datetime.fromtimestamp运行它(我知道你使用的是Python 3,但这就是我所拥有的),这表明它认为它指的是2010-04-04 02: 00:00 - 我在CEST,所以这是UTC + 2.

运行datetime.fromtimestamp(0),我知道纪元是1970-01-01 01:00:00。然后,这表明它正确地添加了一个小时(因为1月1日在DST之外,并且纪元是在该日期的午夜UTC,这里将是01:00)。

换句话说,您的问题是您正在发送已应用DST的时间,但datetime_to_timestamp会将其视为DST不存在。但是,timestamp_to_datetime应用DST。

不幸的是,我不知道你会怎么解决这个问题,但这至少应该让你有所作为。