246

我有dt = datetime(2013,9,1,11),我想获得这个 datetime 对象的 Unix 时间戳。

当我这样做时,(dt - datetime(1970,1,1)).total_seconds()我得到了时间戳1378033200

datetime.fromtimestamp当使用I got将其转换回来时datetime.datetime(2013, 9, 1, 6, 0)

小时不匹配。我在这里错过了什么?

4

12 回答 12

172

解决方案是

import time
import datetime
d = datetime.date(2015,1,5)

unixtime = time.mktime(d.timetuple())
于 2015-01-13T03:21:47.623 回答
133

您在这里错过的是时区。

大概你有五个小时的 UTC,所以 2013-09-01T11:00:00 local 和 2013-09-01T06:00:00Z 是同一时间。

您需要阅读datetime文档的顶部,其中解释了时区以及“天真”和“感知”对象。

如果您最初的原始日期时间是 UTC,则恢复它的方法是使用utcfromtimestamp而不是fromtimestamp.

另一方面,如果您最初的原始日期时间是本地的,那么您首先不应该从中减去 UTC 时间戳;改为使用datetime.fromtimestamp(0)

或者,如果您有一个感知日期时间对象,您需要在双方都使用本地(感知)纪元,或者显式转换为 UTC。

如果您拥有或可以升级到 Python 3.3 或更高版本,则只需使用该timestamp方法即可避免所有这些问题,而不是尝试自己弄清楚如何去做。即使你不这样做,你也可以考虑借用它的源代码

(如果你可以等待 Python 3.4,看起来PEP 341很可能会进入最终版本,这意味着 JF Sebastian 和我在评论中讨论的所有内容都应该只使用 stdlib 就可以实现,并且在 Unix 和 Windows 上以相同的方式工作。)

于 2013-11-06T00:27:09.903 回答
128

如果要将 python 日期时间转换为自纪元以来的秒数,则应明确执行:

>>> import datetime
>>> datetime.datetime(2012, 04, 01, 0, 0).strftime('%s')
'1333234800'
>>> (datetime.datetime(2012, 04, 01, 0, 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1333238400.0

在 Python 3.3+ 中,您可以timestamp()改用:

>>> import datetime
>>> datetime.datetime(2012, 4, 1, 0, 0).timestamp()
1333234800.0
于 2017-01-23T17:03:59.633 回答
54

而不是这个表达式来创建一个 POSIX 时间戳dt

(dt - datetime(1970,1,1)).total_seconds()

用这个:

int(dt.strftime("%s"))

我使用第二种方法在您的示例中得到了正确的答案。

编辑:一些后续行动......经过一些评论(见下文),我很好奇%sin缺乏支持或文档strftime。这是我发现的:

在 and 的Python源代码中,字符串告诉我们:datetimetimeSTRFTIME_FORMAT_CODES

"Other codes may be available on your platform.
 See documentation for the C library strftime function."

所以现在如果我们man strftime(在 BSD 系统上,比如 Mac OS X),你会发现支持%s

"%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3))."

无论如何,这就是为什么%s在它的系统上工作的原因。但是对于 OP 的问题有更好的解决方案(考虑时区)。在此处查看@abarnert 接受的答案。

于 2013-11-06T00:32:51.567 回答
11

使用 UTC 时区:

time_stamp = calendar.timegm(dt.timetuple())

datetime.utcfromtimestamp(time_stamp)
于 2018-09-25T16:51:07.700 回答
7

您错过了时区信息(已回答,同意)

arrow允许避免这种日期时间的折磨;它已经编写、测试、pypi-published、cross-python (2.6 - 3.xx)。

所有你需要的:(pip install arrow或添加到依赖项)

适合您的情况的解决方案

dt = datetime(2013,9,1,11)
arrow.get(dt).timestamp
# >>> 1378033200

bc = arrow.get(1378033200).datetime
print(bc)
# >>> datetime.datetime(2013, 9, 1, 11, 0, tzinfo=tzutc())
print(bc.isoformat())
# >>> '2013-09-01T11:00:00+00:00'
于 2017-09-01T13:02:35.867 回答
7

如果您的 datetime 对象表示 UTC 时间,请不要使用 time.mktime,因为它假定元组位于您的本地时区。相反,使用 calendar.timegm:

>>> import datetime, calendar
>>> d = datetime.datetime(1970, 1, 1, 0, 1, 0)
>>> calendar.timegm(d.timetuple())
60
于 2017-11-28T06:39:37.427 回答
2

好吧,当转换为 unix 时间戳时,python 基本上假设 UTC,但是在转换回来时,它会给你一个转换为本地时区的日期。

请参阅此问题/答案; 获取 datetime.datetime.fromtimestamp() 使用的时区

于 2013-11-06T00:33:25.537 回答
2
def dt2ts(dt, utc=False):
    if utc:
        return calendar.timegm(dt.timetuple())
    if dt.tzinfo is None:
        return int(time.mktime(dt.timetuple()))
    utc_dt = dt.astimezone(tz.tzutc()).timetuple()
    return calendar.timegm(utc_dt)

如果您想要 UTC 时间戳:time.mktime仅用于本地dt 。使用calendar.timegm是安全的,但 dt 必须是 utc 区域,因此将区域更改为 utc。如果 UTC 中的 dt 只需使用calendar.timegm.

于 2017-11-29T04:00:44.637 回答
2
def datetime_to_epoch(d1):

    # create 1,1,1970 in same timezone as d1
    d2 = datetime(1970, 1, 1, tzinfo=d1.tzinfo)
    time_delta = d1 - d2
    ts = int(time_delta.total_seconds())
    return ts


def epoch_to_datetime_string(ts, tz_name="UTC"):
    x_timezone = timezone(tz_name)
    d1 = datetime.fromtimestamp(ts, x_timezone)
    x = d1.strftime("%d %B %Y %H:%M:%S")
    return x
于 2019-08-09T09:24:40.247 回答
1

此类将满足您的需求,您可以将变量传递给 ConvertUnixToDatetime 并根据需要调用您希望它运行的函数。

from datetime import datetime
import time

class ConvertUnixToDatetime:
    def __init__(self, date):
        self.date = date

    # Convert unix to date object
    def convert_unix(self):
        unix = self.date

        # Check if unix is a string or int & proceeds with correct conversion
        if type(unix).__name__ == 'str':
            unix = int(unix[0:10])
        else:
            unix = int(str(unix)[0:10])

        date = datetime.utcfromtimestamp(unix).strftime('%Y-%m-%d %H:%M:%S')

        return date

    # Convert date to unix object
    def convert_date(self):
        date = self.date

        # Check if datetime object or raise ValueError
        if type(date).__name__ == 'datetime':
            unixtime = int(time.mktime(date.timetuple()))
        else:
            raise ValueError('You are trying to pass a None Datetime object')
        return type(unixtime).__name__, unixtime


if __name__ == '__main__':

    # Test Date
    date_test = ConvertUnixToDatetime(datetime.today())
    date_test = date_test.convert_date()
    print(date_test)

    # Test Unix
    unix_test = ConvertUnixToDatetime(date_test[1])
    print(unix_test.convert_unix())
于 2020-02-21T06:14:52.367 回答
0
import time
from datetime import datetime
time.mktime(datetime.now().timetuple())
于 2022-01-07T01:11:44.193 回答