如何在 Python 中将日期时间对象转换为自纪元(unix 时间)以来的毫秒数?
Posted
技术标签:
【中文标题】如何在 Python 中将日期时间对象转换为自纪元(unix 时间)以来的毫秒数?【英文标题】:How can I convert a datetime object to milliseconds since epoch (unix time) in Python? 【发布时间】:2011-10-23 09:43:30 【问题描述】:我有一个 Python datetime
对象,我想将其转换为 unix 时间,或自 1970 年以来的秒/毫秒。
我该怎么做?
【问题讨论】:
相关:Converting datetime.date to UTC timestamp in Python 如果您登陆这里只是想要毫秒精度的 当前 纪元秒,请尝试$ python -c 'import time; print(time.time())'
,它给出:1584487455.698623
@MarkHu 这似乎是微秒精度。
【参考方案1】:
>>> import datetime
>>> # replace datetime.datetime.now() with your datetime object
>>> int(datetime.datetime.now().strftime("%s")) * 1000
1312908481000
或者时间模块的帮助(并且没有日期格式):
>>> import datetime, time
>>> # replace datetime.datetime.now() with your datetime object
>>> time.mktime(datetime.datetime.now().timetuple()) * 1000
1312908681000.0
在http://pleac.sourceforge.net/pleac_python/datesandtimes.html的帮助下回答了
文档:
time.mktime
datetime.timetuple
【讨论】:
顺便说一句,strftime("%s") 为我返回一个空字符串。第二种方法效果很好。 只有秒精度 '%s' 不受 Python 支持,例如,它在 Windows 上可能不存在。.timetuple()
返回 tm_isdst=-1
它迫使 mktime()
猜测。它可能会在 DST 期间猜错(50% 的错误几率 +/- 小时)。 '%s' 和 mktime()
都可能对过去的日期使用错误的 UTC 偏移量。您需要一个历史时区数据库,例如 pytz
模块提供的以可靠地将本地时间转换为 POSIX 时间戳(除非操作系统已经提供了这样的数据库)
time.mktime(ts.timetuple())
其中 ts 是 python 的日期时间对象
@suhail:阅读我上面关于mktime/timetuple
的评论。 timetuple()
也去除了几分之一秒,问题的关键是要获得毫秒精度的时间戳。【参考方案2】:
import time
seconds_since_epoch = time.mktime(your_datetime.timetuple()) * 1000
【讨论】:
这是错误的!时间元组不包括毫秒,因此 mktime 不会返回毫秒分辨率的纪元。在这种情况下它是没有用的。 @Wang - 你是对的先生,这不会返回毫秒,只有几秒钟 见my comment about timetuple/mktime 如果你删除* 1000
,你会得到seconds_since_epoch
。赞成这个答案,因为我现在不关心毫秒。【参考方案3】:
在我看来,最简单的方法是
import datetime
epoch = datetime.datetime.utcfromtimestamp(0)
def unix_time_millis(dt):
return (dt - epoch).total_seconds() * 1000.0
【讨论】:
到目前为止,这是最好的解决方案(如果 python 版本 >2.7)。因为%s
的实现取决于操作系统!因此,任何人都希望代码可靠地工作,无论在哪个操作系统上,都不应使用%s
。对于 2.3 total_seconds():delta.days*86400+delta.seconds+delta.microseconds/1e6
注意:dt
必须是 UTC(不是本地)。见similar answer with Python 2.6/3 support
值得一提的是,如果您想要的只是此处定义的真正的 unix 时间戳en.wikipedia.org/wiki/Unix_time (因此只会使用此答案中的 unix_time 函数),那么您应该将 delta.total_seconds() 包装为int 以避免以浮点数结束
使用utcfromtimestamp(0)
计算的纪元只有在'tz' 不为0 时才可能导致'tz' 偏移。这是因为dt- epoch
中的dt
在其中计算了'tz' 纪元是 UTC 时间。计算纪元的最佳方法是epoch = datetime.datetime(1970, 1, 1)
,其中考虑了时区。
为什么datetime.utcfromtimestamp(0)
返回一个没有tzinfo 的日期时间?它就在方法名称中,utcfromtimestamp。为了使它不幼稚,我必须做类似datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC)
的事情。如果dt
可以识别时区,则这是必要的,否则您将获得TypeError: can't subtract offset-naive and offset-aware datetimes
【参考方案4】:
这就是我的做法:
from datetime import datetime
from time import mktime
dt = datetime.now()
sec_since_epoch = mktime(dt.timetuple()) + dt.microsecond/1000000.0
millis_since_epoch = sec_since_epoch * 1000
【讨论】:
见my comment about timetuple/mktime @J.F.Sebastian 感谢您的提醒!确实没有考虑dst。如果您的服务器是本地时间而不是 UTC,那么它会有所作为。我还没有找到任何令人信服的理由来设置除 UTC 以外的任何服务器。我的 moto 是“写 UTC,读本地时间”,所以你总是知道你住在哪里...... 您可以随时使用 calendar.timegm 代替 mktime 来避免 mktime 试图猜测时区的问题。【参考方案5】:>>> import datetime
>>> import time
>>> import calendar
>>> #your datetime object
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2013, 3, 19, 13, 0, 9, 351812)
>>> #use datetime module's timetuple method to get a `time.struct_time` object.[1]
>>> tt = datetime.datetime.timetuple(now)
>>> tt
time.struct_time(tm_year=2013, tm_mon=3, tm_mday=19, tm_hour=13, tm_min=0, tm_sec=9, tm_wday=1, tm_yday=78, tm_isdst=-1)
>>> #If your datetime object is in utc you do this way. [2](see the first table on docs)
>>> sec_epoch_utc = calendar.timegm(tt) * 1000
>>> sec_epoch_utc
1363698009
>>> #If your datetime object is in local timeformat you do this way
>>> sec_epoch_loc = time.mktime(tt) * 1000
>>> sec_epoch_loc
1363678209.0
[1]http://docs.python.org/2/library/datetime.html#datetime.date.timetuple
[2]http://docs.python.org/2/library/time.html
【讨论】:
【参考方案6】:你可以使用 Delorean 穿越时空!
import datetime
import delorean
dt = datetime.datetime.utcnow()
delorean.Delorean(dt, timezone="UTC").epoch
http://delorean.readthedocs.org/en/latest/quickstart.html
【讨论】:
【参考方案7】:from datetime import datetime
from calendar import timegm
# Note: if you pass in a naive dttm object it's assumed to already be in UTC
def unix_time(dttm=None):
if dttm is None:
dttm = datetime.utcnow()
return timegm(dttm.utctimetuple())
print "Unix time now: %d" % unix_time()
print "Unix timestamp from an existing dttm: %d" % unix_time(datetime(2014, 12, 30, 12, 0))
【讨论】:
timegm()
仅适用于 UTC 时间。它不使用tm_isdst
,因此您可以使用utcnow.timetuple()
而不是utcnow.utctimetuple()
。注意:在这里使用naive_local_datetime.utctimetuple()
是错误的。它不会将当地时间转换为 UTC。此外,timetuple()
调用会从结果中删除几分之一秒(是否重要取决于应用程序)。该问题还询问 *milli*秒,而不是秒
我更喜欢使用 utcnow() 和 utctimetuple() 使代码绝对清楚你正在处理 UTC(这样任何阅读它的人都不必记住 timegm 只是 UTC )。 utctimetuple() 并不意味着对天真的 dttm 对象进行翻译(因此使用 utcnow() 初始化 dttm)。另外,问题提到了秒或毫秒。
注意:应该在最后的评论中说我读到这个问题暗示他想要几秒钟或几毫秒(可能是我的错误)。对于毫秒,只需乘以 1000(如得分最高的答案所示)。
utctimetuple()
去除几分之一秒。乘以 1000
不会让他们回来。
由于 OP 提出这个问题的方式,不清楚他/她到底想要什么(即真正的 unix 时间戳或毫秒精度的时间戳)。无论如何,这两个问题都已经在其他地方提出并回答了。话虽如此,我认为这里的答案对于人们来说是最快和最干净的,并且很好地说明了问题的各种解决方案。【参考方案8】:
在 Python 3.3 中,添加了新方法 timestamp
:
import datetime
seconds_since_epoch = datetime.datetime.now().timestamp()
你的问题表明你需要毫秒,你可以这样得到:
milliseconds_since_epoch = datetime.datetime.now().timestamp() * 1000
如果你在一个简单的日期时间对象上使用timestamp
,那么它假定它在本地时区。如果您不打算这样做,请使用可识别时区的日期时间对象。
【讨论】:
注意:.timestamp()
方法假定天真的输入日期时间在本地时区(本地时间可能不明确)。如果是 UTC,则使用 dt.replace(tzinfo=timezone.utc).timestamp()
instead。
datetime.timestamp() 以浮点数形式返回纪元秒数。获取毫秒:int(datetime.timestamp() * 1000)
这个答案不是一个可复制粘贴的例子,本着docs.python.org/3/library/… 的非人性化文档的精神——这是:datetime.datetime.timestamp(datetime.datetime.now())
在 3.6 中(至少), datetime.timestamp() 假定时区天真 (tzinfo=None) 日期时间为 UTC。所以最好设置你的时区:datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()
,但不(总是)等于datetime.datetime.now().timestamp()
(如果本地 tz 是 UTC,最后一个只等于其余的......)
为了您的兴趣,反面是]fromtimestamp
(docs.python.org/3/library/…)【参考方案9】:
这是另一种形式的时间对象标准化解决方案:
def to_unix_time(timestamp):
epoch = datetime.datetime.utcfromtimestamp(0) # start of epoch time
my_time = datetime.datetime.strptime(timestamp, "%Y/%m/%d %H:%M:%S.%f") # plugin your time object
delta = my_time - epoch
return delta.total_seconds() * 1000.0
【讨论】:
【参考方案10】:Python 2.7 docs for the time
module 的推荐
【讨论】:
@ChristopherBull 只需将毫秒数除以 1000 即可得到秒数 你误解了,弄错了。秒在上述功能中都已准备就绪。您可以将其转换为毫秒,但它会是一秒的精度。 此答案使用time
模块,但 OP 询问了 datetime
模块。 FWIW,最简单的当前纪元是int(time.time())
【参考方案11】:
另一种将日期时间转换为 unixtimestampmillis 的解决方案。
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static long GetCurrentUnixTimestampMillis()
DateTime localDateTime, univDateTime;
localDateTime = DateTime.Now;
univDateTime = localDateTime.ToUniversalTime();
return (long)(univDateTime - UnixEpoch).TotalMilliseconds;
【讨论】:
问题是关于Python语言的【参考方案12】:一点熊猫代码:
import pandas
def to_millis(dt):
return int(pandas.to_datetime(dt).value / 1000000)
【讨论】:
【参考方案13】:这是我根据上面的答案做的一个函数
def getDateToEpoch(myDateTime):
res = (datetime.datetime(myDateTime.year,myDateTime.month,myDateTime.day,myDateTime.hour,myDateTime.minute,myDateTime.second) - datetime.datetime(1970,1,1)).total_seconds()
return res
你可以像这样包装返回值:str(int(res)) 将其返回不带十进制值用作字符串或仅 int(不带 str)
【讨论】:
【参考方案14】:其中很多答案不适用于 python 2,或者不保留日期时间的毫秒数。这对我有用
def datetime_to_ms_epoch(dt):
microseconds = time.mktime(dt.timetuple()) * 1000000 + dt.microsecond
return int(round(microseconds / float(1000)))
【讨论】:
以上是关于如何在 Python 中将日期时间对象转换为自纪元(unix 时间)以来的毫秒数?的主要内容,如果未能解决你的问题,请参考以下文章