我有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)
。
时间不匹配。我在这里想念什么?
dt
来的?是当地时间还是UTC时间?
我有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)
。
时间不匹配。我在这里想念什么?
dt
来的?是当地时间还是UTC时间?
Answers:
您在这里错过的是时区。
大概您要在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上均以相同的方式工作。)
dt
在当地时区,则问题中的公式不正确datetime.fromtimestamp(0)
(应使用当前时区中的纪元),而不是datetime(1970, 1,1)
(UTC中的unix纪元)。
fromtimestamp(0)
如果系统未存储历史时区信息(例如在Windows上),则可能会失败。pytz
在这种情况下可以使用。
pytz
除非您已经知道您所在的时区,否则它无济于事。要以编程方式执行此操作,您需要一个不同的库来获取当前Windows时区并将其转换pytz
为时区和/或按名称查找。
tzlocal
在Windows上也可以使用的模块。这是将utc时间转换为本地时间的方法。
解决方案是
import time
import datetime
d = datetime.date(2015,1,5)
unixtime = time.mktime(d.timetuple())
如果要将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
%s
,因为它将被本地化为当前使用的系统的时钟。您应该只使用.timestamp()
以获得正确的Epoch / UNIX时间。
%s
在Windows系统上不起作用(ValueError: Invalid format string
)
8
或9
而不是使用此表达式从创建一个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可接受的答案。
strftime("%s")
在文档中看到,但我只是确认了它可以在Mac和Linux上使用。谢谢。
time.strftime()
和datetime.strftime
文档代表对平台strftime(3)
功能不支持的指令。%s
即使在Mac OS X上也可能失败,例如datetime.strftime('%s')应该尊重tzinfo。
%s
因为您将只使用所用系统的本地化系统时间。如果要.timestamp()
获取真实的UNIX时间戳,则要使用。
对于使用UTC时区:
time_stamp = calendar.timegm(dt.timetuple())
datetime.utcfromtimestamp(time_stamp)
您错过了时区信息(已回答,已同意)
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'
好吧,当转换为unix时间戳时,python基本上采用了UTC,但是当转换回它时,它将给您一个转换为本地时区的日期。
看到这个问题/答案; 从datestamp()获取datetime.datetime.date使用的时区
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 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
该类将满足您的需求,您可以将变量传递给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())