【问题标题】:Python: Converting string to timestamp with microsecondsPython:用微秒将字符串转换为时间戳
【发布时间】:2014-11-27 11:05:03
【问题描述】:

我想将字符串日期格式转换为以微秒为单位的时间戳 我尝试以下但未给出预期结果:

"""input string date -> 2014-08-01 04:41:52,117
expected result -> 1410748201.117"""

import time
import datetime

myDate = "2014-08-01 04:41:52,117"
timestamp = time.mktime(datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timetuple())

print timestamp
> 1410748201.0

毫秒去哪儿了?

【问题讨论】:

  • 输入日期(2014-08-01)与时间戳(2014-09-15 02:30:01.117Z)不对应

标签: python datetime timestamp converter


【解决方案1】:

时间元组中没有微秒组件的槽:

>>> import time
>>> import datetime
>>> myDate = "2014-08-01 04:41:52,117"
>>> datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timetuple()
time.struct_time(tm_year=2014, tm_mon=8, tm_mday=1, tm_hour=4, tm_min=41, tm_sec=52, tm_wday=4, tm_yday=213, tm_isdst=-1)

您必须手动添加:

>>> dt = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f")
>>> time.mktime(dt.timetuple()) + (dt.microsecond / 1000000.0)
1406864512.117

您可以遵循的另一种方法是生成一个相对于纪元的timedelta() object,然后使用timedelta.total_seconds() method 获取时间戳:

epoch = datetime.datetime.fromtimestamp(0)
(dt - epoch).total_seconds()

本地时间纪元的使用是经过深思熟虑的,因为您有一个幼稚的(不是时区感知的)日期时间值。但是,根据您当地时区的历史记录,此方法可能不准确,请参阅J.F. Sebastian's comment。您必须先使用本地时区将原始日期时间值转换为可识别时区的日期时间值,然后再减去可识别时区的纪元。

因此,坚持timetuple() + 微秒方法更容易。

演示:

>>> dt = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f")
>>> epoch = datetime.datetime.fromtimestamp(0)
>>> (dt - epoch).total_seconds()
1406864512.117

【讨论】:

  • 1 如果dt 是一个幼稚的本地时间,则(dt - epoch) 不正确。本地时间可能会延迟(北半球秋季的 DST 过渡)。在这种情况下,时间戳应该重新设置。 2 “本地时间”也可能具有误导性。纪元是一个单个时间实例(Python 是 1970 年)——全世界都一样。如果 C 库支持历史时区数据库或本地时区的 UTC 在当时具有相同的值,则 datetime.fromtimestamp(0) 返回对应于纪元的本地时间。
  • @J.F.Sebastian:epoch 值使用 fromtimestamp(),而不是 utcfromtimestamp(),来处理 DST 差异,正是因为 dt 值是幼稚的。
  • @J.F.Sebastian:如果我改用utcfromtimestamp(),我必须首先让dt 感知时区,从而让Python 来弥补DST 问题。
  • 你误会了。问题是该公式使用当地时间。本地时间可能不明确(如果它是输入并且没有其他信息可用,则您无能为力)。并且本地时区的 utc 偏移量可能与过去不同(您需要 tz 数据库才能找到它)。正确的公式:ts = utc_time - epoch_in_utc = local time - utc offset(now) - epoch in local time + utc offset (then)。您的公式相当于现在使用 UTC 偏移量,即它假定 utc offset(now) == utc offset (then)
  • @J.F.Sebastian:啊,好点子。使用适当的时区数据库,公式会更容易。作为一个近似,忽略历史问题,是否足够好?因为time.time() 不使用历史值也不
【解决方案2】:

毫秒去哪儿了?

这是最简单的部分。 .timetuple() 电话会挂断他们。您可以使用 .microsecond 属性将它们添加回来。 datetime.timestamp() method from the standard library 以这种方式适用于天真的日期时间对象:

def timestamp(self):
    "Return POSIX timestamp as float"
    if self._tzinfo is None:
        return _time.mktime((self.year, self.month, self.day,
                             self.hour, self.minute, self.second,
                             -1, -1, -1)) + self.microsecond / 1e6
    else:
        return (self - _EPOCH).total_seconds()

如果可能的话,在您的情况下可以忽略约 1 小时的错误就足够了。我假设您需要微秒,因此您不能默默地忽略约 1 小时的时间错误。

将作为字符串给出的本地时间正确转换为 POSIX 时间戳通常是一项复杂的任务。您可以将本地时间转换为 UTC,然后将 get the timestamp from UTC time.

主要有两个问题:

两者都可以使用 tz 数据库(Python 中的pytz 模块)解决:

from datetime import datetime
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal

tz = get_localzone() # get pytz timezone corresponding to the local timezone

naive_d = datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f")
# a) raise exception for non-existent or ambiguous times
d = tz.localize(naive_d, is_dst=None)
## b) assume standard time, adjust non-existent times
#d = tz.normalize(tz.localize(naive_d, is_dst=False))
## c) assume DST is in effect, adjust non-existent times
#d = tz.normalize(tz.localize(naive_d, is_dst=True))
timestamp = d - datetime(1970, 1, 1, tzinfo=pytz.utc)

结果是timestamp -- 一个timedelta 对象,你可以将其转换为秒、毫秒等。

此外,不同的系统在闰秒前后的行为可能不同。大多数应用程序可以忽略它们的存在。

通常,将 POSIX 时间戳存储到本地时间可能更简单,而不是尝试从本地时间猜测它。

【讨论】:

  • 注意:datetime.timestamp 仅在 Python 3 中可用; OP 正在使用 Python 2(根据 print 语句判断)。
  • @MartijnPieters:我建议使用.timestamp() 方法。我只是将它用作示例(有缺陷的)实现。
  • 我并不是要建议你这样做。我只是指出 Python 2 中不存在该方法。
  • @MartijnPieters:我明白你说的什么。我不明白你说的为什么。在这种情况下,代码恰好包含在 Python 3 标准库中并不重要 + d.microsecond / 1e6 在 Python 2 和 3 上的工作方式相同。
【解决方案3】:

在 Python 3.4 及更高版本中可以使用

timestamp = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timestamp()

这不需要导入time 模块。它还使用更少的步骤,因此应该更快。对于旧版本的 python,其他提供的答案可能是您的最佳选择。

但是,生成的时间戳将以本地时间而不是 UTC 解释 myDate,如果 myDate 以 UTC 给出,这可能会导致问题

【讨论】:

    猜你喜欢
    • 2016-08-01
    • 1970-01-01
    • 2011-04-14
    • 2012-09-17
    • 2021-04-13
    • 1970-01-01
    • 2020-11-22
    • 2017-10-11
    • 1970-01-01
    相关资源
    最近更新 更多