【问题标题】:Conversion of Python DateTime string into integer millisecondsPython DateTime 字符串转换为整数毫秒
【发布时间】:2015-09-14 17:09:05
【问题描述】:

我想将 UTC TimeDate 戳字符串转换为毫秒的整数值(可能需要为 64 位数量),以便在存储在 mySQL 数据库列中时占用更少的空间。这个 UTC 字符串是从另一个库生成的,我将它存储为一种每个用户的 GUID。

datetime 或 dateutil 能否将其转换为单个整数值(如“自纪元以来的毫秒数”)?还是我需要自己做?

使用这种方法解析:

myDateTime = dateutil.parser.parse("2015-06-27T02:10:05.653000Z")
print("Parsed datetime String is {0}, ordinal value is {1}".format(myDateTime, myDateTime.toordinal()))

给出输出:

Parsed datetime String is 2015-06-27 02:10:05.652999+00:00, ordinal value is 735776

…它只给出日期的序数值。此外,如果我有一个整数 653 毫秒的时间,那么我希望该解析的对象知道它有 653 毫秒,而不是 652999。

【问题讨论】:

  • 为什么您认为存储整数或毫秒所需的空间比数据库中的原生 datetime 格式要少?
  • 你可以做类似int(datetime.strptime(time_string, your_format).strftime('%s'))*1e3的事情。这将是自纪元以来以毫秒为单位的浮点数,如果需要,您可以将其转换为 int。
  • @GordonLinoff - 我的意思是比 STRING 表示的空间少。
  • @SMGreenfield 。 . .这不是日期/时间格式在数据库中的工作方式。使用原生格式。
  • @Scott -- 你的建议非常接近,而且正是这种方法。这是我使用的精确语法: int(Decimal(datetime.datetime.strptime("2015-06-27T02:10:05.653000Z", "%Y-%m-%dT%H:%M:%S.%fZ ").strftime('%s.%f'))*1000)) 我假设你的意思是乘以 3e8 (1000),而不是 1e3 (483)....

标签: python mysql python-2.7 datetime datetime-format


【解决方案1】:

[在 cmets 中编辑了以下建议]

使用Ben Alpert's 回复How can I convert a datetime object to milliseconds since epoch (unix time) in Python,我们可以执行以下操作:

from datetime import datetime
def unix_time(dt):
    epoch = datetime.utcfromtimestamp(0)
    delta = dt - epoch
    return delta.total_seconds()

def unix_time_millis(dt):
    return int(unix_time(dt) * 1000)

a = datetime.strptime("2015-06-27T02:10:05.653000Z", "%Y-%m-%dT%H:%M:%S.%fZ")
unix_time_millis(a)

返回:

1435371005653

相当于:2015 年 6 月 27 日星期六 02:10:05 GMT(如预期)

我们也可以使用 datetime 的 .strftime('%s') 来获取 unix 时间,甚至是毫秒,使用以下方法(但不建议这样做):

from decimal import Decimal

int(Decimal(datetime.strptime("2015-06-27T02:10:05.653000Z", "%Y-%m-%dT%H:%M:%S.%fZ").strftime('%s.%f'))*1000)

返回:

1435396205653

相当于:2015 年 6 月 27 日星期六 09:10:05 GMT(在圣地亚哥的我的 Mac 上;注意:这可能是 7 小时的休息时间预期)。

J.F. Sebastian 在上面链接的 cmets 和 this 关于 .strftime('%s') 行为的回答中描述了错误的原因。 JF Sebastian 指出“它不受支持,它不可移植,它可能会默默地为有意识的日期时间对象产生错误的结果,如果输入是 UTC(如问题所示)但本地时区不是 UTC,它会失败”

【讨论】:

  • 我也很困惑,为什么 strftime() 文档中没有列出小写的 %s,但是当它似乎起作用时,我想其他人一定知道得更好。仍然需要注意的是,使用 Z 解析字符串时,其他带有偏移量的 UTC 将无法解析,但我的用例特别限于 Z(祖鲁时间)。我真的很感谢你在这方面的努力!谢谢!
  • 你链接的两个问题都有明确的 cmets 说明为什么你不应该使用 .strftime('%s')
  • @JFSebastian 我实际上在某些情况下使用了.strftime('%s'),其中时区不是一个因素,因此没有意识到这个问题直到我阅读了链接的帖子和 cmets (特别是您的评论)。您认为明确说明 .strftime('%s') 的问题或让用户点击链接有额外的好处吗?
  • 只需将正确的工作解决方案放在答案的顶部即可。在答案的底部,您可以提及为什么不应使用 .strftime('%s')(或仅链接到我的评论)。
  • @J.F.Sebastian 感谢您的建议。根据您的建议进行了编辑。
【解决方案2】:

分为两部分:

【讨论】:

  • 我已经阅读了两篇文章(相当多的讨论!)假设 ZULU-ONLY UTC(我的用例),上述方法是否优于我消除 strftime 的编辑?或者只是更优雅,因为它考虑了解析时区偏移量?
  • @SMGreenfield:如果我们忽略你不应该做的简单的 except:long 用法,那么只有很小的差异(验证、舍入行为、支持的 python 版本)。顺便说一句,不解析时区偏移量;假设 utc 时间(零 utc 偏移)。
  • 这是您在链接中提供的非常详细且参考充分的答案。会仔细研究一段时间。
【解决方案3】:

Scott 和 GordonLinoff 都为解决我的问题提供了出色的帮助。我正在添加完整性的答案。

将 UTC 日期时间字符串转换为自纪元以来的毫秒数的 Python 代码:

已编辑以消除 strftime:

from datetime import datetime

def convert_UTC_zulu_string_to_milliseconds_since_epoch(myUTCzuluString):
    try:
        dt_unix = datetime.strptime(myUTCzuluString, "%Y-%m-%dT%H:%M:%S.%fZ")
        epoch = datetime.utcfromtimestamp(0)
        delta = dt_unix - epoch
        millisecondsSinceEpoch = long(delta.total_seconds() * 1000)

    except:
        millisecondsSinceEpoch = 0L

    return millisecondsSinceEpoch


myUTCzuluString = "2015-06-27T02:10:05.653000Z"
millisecondsSinceEpoch = convert_UTC_zulu_string_to_milliseconds_since_epoch(myUTCzuluString)
print("Milliseconds since epoch: {0}".format(millisecondsSinceEpoch))

另外:如果我将列定义为 DATETIME(6) 数据类型,mysql 将直接从字符串中接受毫秒/微秒的日期时间值:

UPDATE myTable SET myDateTimeField = '2015-06-27T02:10:05.653000Z'

请注意,在 UTC 日期时间字符串的末尾包含“Z”会导致来自 mysql 的截断警告。

我无法确定 DATETIME(6) 超过 DATETIME 的附加精度是否导致 mysql 的 InnoDB 引擎使用超过 8 个字节,这是我研究该问题的最初原因之一。

【讨论】:

  • 我认为要走的路(并亲自使用过)结果可能存在错误。所以,除非你住在 gmt,否则你可能不想使用 %s。
  • 你可能已经知道了,但是这里有一些关于 mysql 分数时间/日期的讨论 stackoverflow.com/a/26299379/4663466 并且有一个内置的 mysql UNIX_TIMESTAMP() dev.mysql.com/doc/refman/5.7/en/…
  • 除非您的本地时区是 utc,否则不要将 .strftime('%s') 与 utc 输入一起使用。
  • 可能值得考虑使用适当的mysql DATE类型插入格式为%Y-%m-%dT%H:%M:%S.%fZ的硅藻土对象,并且当您需要以毫秒为单位的unix时间时,使用内置的mysql UNIX_TIMESTAMP(date)(假设它处理带小数秒并输出到毫秒)。我没有这方面的经验,所以请调查一下,但这可能比在插入之前转换为 unix 时间以及在获取之后转换为人类可读的时间要快。
  • @Scott -- 在采用这种方法之前,我需要调查 1)为什么 mysql DATETIME(6) 类型会在时间字符串以“Z”结尾时发出警告,以及 2)有多少字节DATETIME(6) 使用。
猜你喜欢
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
相关资源
最近更新 更多