如何在 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 时间)以来的毫秒数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中将日期转换为纪元时间[重复]

如何在 python 中将普通时间戳转换为纪元时间戳

将日期、时间和 UTC 偏移值转换为自 unix 纪元以来的毫秒数?

在 Python 中将一列日期时间转换为纪元

如何在 Perl 中将日期转换为纪元时间?

如何在javascript中将给定的日期和时间转换为纪元时间?