问题:将datetime转换为Unix时间戳并将其转换回python

我有dt = datetime(2013,9,1,11),并且我想获取此datetime对象的Unix时间戳。

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

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

时间不匹配。我在这里想念什么?

I have dt = datetime(2013,9,1,11), and I would like to get a Unix timestamp of this datetime object.

When I do (dt - datetime(1970,1,1)).total_seconds() I got the timestamp 1378033200.

When converting it back using datetime.fromtimestamp I got datetime.datetime(2013, 9, 1, 6, 0).

The hour doesn’t match. What did I miss here?


回答 0

您在这里错过的是时区。

大概您要在UTC下班5个小时,因此2013-09-01T11:00:00本地和2013-09-01T06:00:00Z是同一时间。

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

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

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

或者,如果您有一个已知的日期时间对象,则需要在两侧都使用一个本地(感知)纪元,或者显式地与UTC进行转换。

如果您拥有或可以升级到Python 3.3或更高版本,则可以通过仅使用timestamp方法来避免所有这些问题,而不必尝试自己弄清楚该如何做。即使您不这样做,也可能要考虑借鉴其源代码

(而且,如果您可以等待Python 3.4,则似乎PEP 341可能会进入最终发行版,这意味着JF Sebastian和我在评论中谈论的所有内容都只能使用stdlib来完成,并且在Unix和Windows上均以相同的方式工作。)

What you missed here is timezones.

Presumably you’ve five hours off UTC, so 2013-09-01T11:00:00 local and 2013-09-01T06:00:00Z are the same time.

You need to read the top of the datetime docs, which explain about timezones and “naive” and “aware” objects.

If your original naive datetime was UTC, the way to recover it is to use instead of fromtimestamp.

On the other hand, if your original naive datetime was local, you shouldn’t have subtracted a UTC timestamp from it in the first place; use datetime.fromtimestamp(0) instead.

Or, if you had an aware datetime object, you need to either use a local (aware) epoch on both sides, or explicitly convert to and from UTC.

If you have, or can upgrade to, Python 3.3 or later, you can avoid all of these problems by just using the timestamp method instead of trying to figure out how to do it yourself. And even if you don’t, you may want to consider borrowing its source code.

(And if you can wait for Python 3.4, it looks like PEP 341 is likely to make it into the final release, which means all of the stuff J.F. Sebastian and I were talking about in the comments should be doable with just the stdlib, and working the same way on both Unix and Windows.)


回答 1

解决方案是

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

unixtime = time.mktime(d.timetuple())

solution is

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

unixtime = time.mktime(d.timetuple())

回答 2

如果要将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

If you want to convert a python datetime to seconds since epoch you should do it explicitly:

>>> 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

In Python 3.3+ you can use timestamp() instead:

>>> import datetime
>>> datetime.datetime(2012,4,1,0,0).timestamp()
1333234800.0

回答 3

而不是使用此表达式从创建一个POSIX时间戳dt

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

用这个:

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

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

编辑:一些跟进…经过一些评论(请参阅下文),我很好奇缺少%sin 的支持或文档strftime。这是我发现的:

Python源datetimetime,串STRFTIME_FORMAT_CODES告诉我们:

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

所以现在,如果我们man strftime(在Mac OS X等BSD系统上)可以找到对以下内容的支持%s

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

无论如何,这就是为什么%s可以在它可以运行的系统上工作。但是有更好的解决OP问题的方法(考虑了时区)。请参阅此处的@abarnert可接受的答案。

Rather than this expression to create a POSIX timestamp from dt,

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

Use this:

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

I get the right answer in your example using the second method.

EDIT: Some followup… After some comments (see below), I was curious about the lack of support or documentation for %s in strftime. Here’s what I found:

In the Python source for datetime and time, the string STRFTIME_FORMAT_CODES tells us:

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

So now if we man strftime (on BSD systems such as Mac OS X), you’ll find support for %s:

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

Anyways, that’s why %s works on the systems it does. But there are better solutions to OP’s problem (that take timezones into account). See @abarnert’s accepted answer here.


回答 4

对于使用UTC时区:

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

datetime.utcfromtimestamp(time_stamp)

For working with UTC timezones:

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

datetime.utcfromtimestamp(time_stamp)

回答 5

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

arrow包装允许避免约会时间的折磨;它已经被编写,测试,pypi发布,交叉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'

You’ve missed the time zone info (already answered, agreed)

arrow package allows to avoid this torture with datetimes; It is already written, tested, pypi-published, cross-python (2.6 — 3.xx).

All you need: pip install arrow (or add to dependencies)

Solution for your case

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'

回答 6

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

>>> import datetime, calendar
>>> d = datetime.datetime(1970, 1, 1, 0, 1, 0)
>>> calendar.timegm(d.timetuple())
60

If your datetime object represents UTC time, don’t use time.mktime, as it assumes the tuple is in your local timezone. Instead, use calendar.timegm:

>>> import datetime, calendar
>>> d = datetime.datetime(1970, 1, 1, 0, 1, 0)
>>> calendar.timegm(d.timetuple())
60

回答 7

好吧,当转换为unix时间戳时,python基本上采用了UTC,但是当转换回它时,它将给您一个转换为本地时区的日期。

看到这个问题/答案; 从datestamp()获取datetime.datetime.date使用的时区

Well, when converting TO unix timestamp, python is basically assuming UTC, but while converting back it will give you a date converted to your local timezone.

See this question/answer; Get timezone used by datetime.datetime.fromtimestamp()


回答 8

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

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)

If you want UTC timestamp :time.mktime just for local dt .Use calendar.timegm is safe but dt must the utc zone so change the zone to utc. If dt in UTC just use calendar.timegm.


回答 9

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
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

回答 10

该类将满足您的需求,您可以将变量传递给ConvertUnixToDatetime&call,然后基于该变量来运行该函数。

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())

This class will cover your needs, you can pass the variable into ConvertUnixToDatetime & call which function you want it to operate based off.

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())

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。