【问题标题】:datetime to Unix timestamp with millisecond precisiondatetime 到 Unix 时间戳,精度为毫秒
【发布时间】:2011-12-30 21:47:42
【问题描述】:

我正在尝试做一些非常简单的事情,将三天后的 datetime 对象转换为 Unix UTC 时间戳:

import datetime, time
then = datetime.datetime.now() + datetime.timedelta(days=3)
# Method 1
print then.strftime("%s")
# Method 2
print time.mktime(then.timetuple())
# Method 3 
print time.mktime(then.timetuple()) * 1000

方法 1 和 2 以 为单位提供 Unix 时间,而不是毫秒,方法 3 以毫秒为单位,但没有实际的毫秒精度。

当我简单地打印then 时,我得到datetime.datetime(2011, 11, 19, 15, 16, 8, 278271),所以我知道精度可以达到毫秒。如何获得具有实际毫秒精度的 Unix 时间戳?如果它作为浮点数返回并且我必须将其展平为int,那很好。有没有我正在寻找的解决方案?

【问题讨论】:

标签: python datetime


【解决方案1】:

日期时间对象有一个名为microsecond 的字段。因此,实现您需要的一种方法是:

time.mktime(then.timetuple())*1e3 + then.microsecond/1e3

这会以所需的精度返回自 UNIX 纪元以来的毫秒数。

【讨论】:

  • 你错过了妙语:print time.mktime(then.timetuple()) * 1000 + then.microsecond/1000
  • 不错的解决方案,尤其是使用1e3而不是1000来保存一个字符的超级黑客。
  • Naftuli,不是真的,因为 1e3 涉及 3 个不同的字符(1、e、3),而 1000 只使用 2 个(1 和 0)
  • 也许我遗漏了一些东西,但微秒是数百万秒而不是千分之一。另外,我不知道为什么你先乘然后除。 time.mktime(then.timetuple()) + then.microsecond/1e6 为我工作。
  • @TheHerk 我不确定,但我认为他想要以毫秒为单位的结果。您的解决方案给出秒数,以毫秒为小数位。
【解决方案2】:

如果您使用的是 Python 2.7 或 3.2+,则可以使用 timedelta.total_seconds() 相当轻松地获得此功能:

import datetime, time
print time.time() + datetime.timedelta(days=3).total_seconds()

【讨论】:

【解决方案3】:
long((time.time() + 0.5) * 1000)

这具有毫秒精度

【讨论】:

  • 什么我必须得到时间戳到小数点后 7 位是这样的:1469172167.3014405
【解决方案4】:

在 Python 3.3 及以上,支持datetime.timestamp() 方法,你可以这样做:

from datetime import datetime, timezone, timedelta

(datetime.now(timezone.utc) + timedelta(days=3)).timestamp() * 1e3

【讨论】:

  • 这应该是公认的答案。
【解决方案5】:

在 POSIX 时间中,日期始终为 86400 秒。获取未来 3 天的 POSIX 时间戳作为浮点数(不到一秒):

import time

DAY = 86400 # seconds
future = time.time() + 3 * DAY

假设time.gmtime(0) 是 1970(POSIX 纪元)。

如果您已经有一个表示本地时区时间的原始 datetime 对象,则时间戳在 DST 转换期间可能不明确。为避免歧义,您可以使用时区感知日期时间对象或以 UTC 表示时间的天真日期时间对象。

要将本地日期时间dt 转换为纪元以来的秒数:

from datetime import datetime
from time import mktime

timestamp = dt.timestamp() # Python 3.3+
timestamp = mktime(dt.timetuple()) + dt.microsecond / 1e6 # Python 2.7

如果本地时区过去有不同的 utc 偏移量并且time 实现无法访问系统上的时区数据库,它可能会失败。使用pytz处理此类情况。

将 UTC 日期时间 utc_dt 转换为 POSIX 时间戳:

timestamp = (utc_dt - datetime(1970, 1, 1)).total_seconds()

要获得毫秒,只需将任意浮点数乘以 1e3。

【讨论】:

  • 谢谢!注意,应该是dt.microsecond,而不是dt.microseconds
【解决方案6】:

如果坚持使用 UTC 中的日期时间,您可以保留该抽象并利用 timedelta:

from datetime import datetime, timedelta

epoch = datetime.utcfromtimestamp(0)

def dt_from_ms(ms):
    return datetime.utcfromtimestamp(ms / 1000.0)

def dt_to_ms(dt):
    delta = dt - epoch
    return int(delta.total_seconds() * 1000)

然后:

now = datetime.utcnow()
now
-> datetime.datetime(2017, 1, 25, 1, 30, 42, 765846)  # note microsecond precision

dt_to_ms(now)
-> 1485307842765

dt_from_ms(1485307842765)
-> datetime.datetime(2017, 1, 25, 1, 30, 42, 765000)  # note millisecond precision

then = now + timedelta(days=3)
dt_to_ms(then)
-> 1485567042765

(1485567042765 - 1485307842765) / (24*60*60*1000.0)
-> 3.0

【讨论】:

    【解决方案7】:

    假设有人对 UTC 感兴趣,以下在 Python 3.3 之后有效:

    from datetime import datetime
    
    now = int(datetime.utcnow().timestamp()*1e3)
    

    Python 3.3 release notes:

    新的datetime.datetime.timestamp() 方法:返回与datetime 实例对应的POSIX 时间戳。

    中间结果:

    In [1]: datetime.utcnow().timestamp()
    Out[1]: 1582562542.407362
    
    In [2]: datetime.utcnow().timestamp()*1e3
    Out[2]: 1582562566701.329
    
    In [3]: int(datetime.utcnow().timestamp()*1e3)
    Out[3]: 1582562577296
    

    【讨论】:

    • 注意:仅当本地时区为 UTC 时才正确。 datetime.utcnow() 返回一个简单的时间戳 (!)。在其上调用方法 .timestamp() 时,假定为本地时区 - 这给出了错误的 POSIX 时间戳。
    • 感谢@HåkonT。!我将链接来自这个 SO 答案的解释:stackoverflow.com/questions/28573873/…
    猜你喜欢
    • 2018-10-10
    • 2013-04-18
    • 1970-01-01
    • 2014-03-20
    • 2021-08-06
    • 1970-01-01
    • 2014-08-07
    • 2018-06-25
    相关资源
    最近更新 更多