Python麻烦将毫秒转换为日期时间并返回

Posted

技术标签:

【中文标题】Python麻烦将毫秒转换为日期时间并返回【英文标题】:Python trouble converting milliseconds to datetime and back 【发布时间】:2015-07-03 09:44:57 【问题描述】:

所以我有两个函数用于将 python datetime.datetime() 对象转换为毫秒数。我无法弄清楚这是哪里出了问题。这是我正在使用的:

>>> import datetime
>>> def mil_to_date(mil):
    """date items from REST services are reported in milliseconds,
    this function will convert milliseconds to datetime objects

    Required:
        mil -- time in milliseconds
    """
    if mil == None:
        return None
    elif mil < 0:
        return datetime.datetime.utcfromtimestamp(0) + datetime.timedelta(seconds=(mil/1000))
    else:
        return datetime.datetime.fromtimestamp(mil / 1000)

>>> def date_to_mil(date):
    """converts datetime.datetime() object to milliseconds

    date -- datetime.datetime() object"""
    if isinstance(date, datetime.datetime):
        epoch = datetime.datetime.utcfromtimestamp(0)
        return long((date - epoch).total_seconds() * 1000.0)

>>> mil = 1394462888000
>>> date = mil_to_date(mil)
>>> date
datetime.datetime(2014, 3, 10, 9, 48, 8)  #this is correct
>>> d2m = date_to_mil(date)
>>> d2m
1394444888000L
>>> mil
1394462888000L
>>> date2 = mil_to_date(d2m)
>>> date2
datetime.datetime(2014, 3, 10, 4, 48, 8) #why did I lose 5 hours??

由于某种原因,我失去了 5 个小时。我是否忽略了一些明显的东西?还是我的一项或两项功能有问题?

【问题讨论】:

这是因为fromtimestamp返回本地时间:“如果可选参数tz为None或未指定,则时间戳转换为平台的本地日期和时间,返回的datetime对象是naive” 无关:timedelta(milliseconds=mil) 工作。 相关:Get current time in milliseconds in Python? 无关:即使结果是long,你也可以使用int(2**300) 1394462888000 != 1394444888000 【参考方案1】:

原因是date_to_mil 可以与UTC 一起使用,而mil_to_date 不能。您应该将utcfromtimestamp 替换为fromtimestamp

进一步解释:

在您的代码中,epoch 是 UTC 纪元的日期(但该对象没有任何时区)。但是date 是本地时间,因为fromtimestamp 返回本地时间:

如果可选参数 tz 为 None 或未指定,则时间戳为 转换为平台的本地日期和时间,并返回 datetime 对象很幼稚

因此,您从本地日期时间中减去 UTC 纪元,您会得到一个延迟,即您对 UTC 的本地延迟。

【讨论】:

哦,哇,我错过了一些明显的东西!我应该将两者都视为UTC。我没有注意到纪元之后所有日期的 else 语句都没有使用 .utcfromtimestamp() 方法。谢谢! @crmackey:应该强调的是,从本地日期时间中减去 UTC 纪元就像从公斤中减去磅 - 结果是无意义的(应该从 utc 时间中减去 utc 纪元。如果本地时区过去有不同的 UTC 偏移量,然后对表示具有不同 UTC 偏移量的本地时间的原始日期时间对象执行算术也是错误的。请参阅Find if 24 hrs have passed between datetimes)【参考方案2】:

如果input is UTC then to get POSIX timestamp 为整数毫秒:

from datetime import datetime, timedelta

def timestamp_millis(utc_time, epoch=datetime(1970, 1, 1)):
    """Return milliseconds since Epoch as integer."""
    td = utc_time - epoch
    return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) // 10**3

注意:公式可能会产生与int(td.total_seconds() * 1000) 不同的结果。

反过来:从以毫秒为单位的 POSIX 时间获取 UTC 时间:

def datetime_from_millis(millis, epoch=datetime(1970, 1, 1)):
    """Return UTC time that corresponds to milliseconds since Epoch."""
    return epoch + timedelta(milliseconds=millis)

它支持正负millis

注意:None 处理发生在这些函数之外。

例子:

>>> datetime_from_millis(1394462888000)
datetime.datetime(2014, 3, 10, 14, 48, 8)
>>> datetime.utcfromtimestamp(1394462888)
datetime.datetime(2014, 3, 10, 14, 48, 8)
>>> timestamp_millis(_)
1394462888000

结果与你的问题不同!

gmtime(0).year != 1970TZ=right/UTC 的情况会被忽略。

【讨论】:

以上是关于Python麻烦将毫秒转换为日期时间并返回的主要内容,如果未能解决你的问题,请参考以下文章

Joda Time 将时区日期时间转换为毫秒

Angularjs日期过滤器将时间毫秒转换为UTC不起作用

js 时间转换毫秒的四种方法(转)

如何将日期时间对象转换为毫秒

如何在 Python 中将日期时间对象转换为自纪元(unix 时间)以来的毫秒数?

在Android中将日期和时间转换为毫秒