问题:将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,则恢复它的方法是使用utcfromtimestamp
而不是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 utcfromtimestamp
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"))
在使用第二种方法的示例中,我得到了正确的答案。
编辑:一些跟进…经过一些评论(请参阅下文),我很好奇缺少%s
in 的支持或文档strftime
。这是我发现的:
在Python源的datetime
和time
,串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
回答 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())