【问题标题】:How to test if a given time-stamp is in seconds or milliseconds?如何测试给定的时间戳是以秒还是毫秒为单位?
【发布时间】:2014-07-18 17:04:07
【问题描述】:

假设一个给定的变量,它包含一个UNIX时间戳,但它是秒还是毫秒格式是未知的,我想分配一个秒格式的变量

例如:

unknown = 1398494489444 # This is millisecond
t = ???

更新:我知道如果不给出一些限制就无法判断,所以在这里

  • current_ts - 86400 * 365

Assume current_ts = current unix timestamp

【问题讨论】:

  • 不知道更多我会说这是不可能的。例如1970-01-01 在 ms 和 s 中是一样的。
  • @frlan,好的,除了 0
  • 好吧。 1970-01-01 之后的 10ms 和 1970-01-01 之后的 10s 是什么...看起来与第二个的 ms 或 s 几乎相同。
  • @Ryan 您将如何(手动)确定一个数字在 Epoch 之后是 ms 还是 s?
  • 除非时间戳周围有上下文线索,否则这是不可能的。你知道它是什么实际日期?以秒为单位的可能时间间隔是否与以毫秒为单位的可能时间间隔重叠?

标签: python datetime timestamp unix-timestamp


【解决方案1】:

如果您 convert 以毫秒为单位 x 位的最大时间戳值,您会得到如下结果:

  • 9999999999999(13 位)表示 11 月 20 日星期六 2286 年 17:46:39 UTC
  • 999999999999(12 位)表示 2001 年 9 月 9 日星期日 01:46:39 UTC
  • 99999999999(11 位)表示 1973 年 3 月 3 日星期六 09:46:39 UTC

您的时间戳可以早于 2001 年吗?如果不是,我认为您可以安全地检查该号码是否有 13 位或更多位 - 如果是,您有毫秒,如果没有,您有秒。当然,这只会在以秒为单位的时间戳也有 13 位之前有效,这意味着以毫秒为单位的时间戳将有 16 位:

  • 1000000000000000(16 位数字)表示 9 月 27 日星期五 33658 01:46:40 但到那时我将生活在半人马座阿尔法系统的行星上,时间标准可能会有所改变:)

附:如果您的时间戳不能追溯到 1973 年以后,您可以将条件放宽到 12 位或更多。该条件只能在以下情况下正常使用:

  • 100000000000000(15 位)表示 11 月 16 日星期三 5138 09:46:40 因为这在几秒钟内将有 12 位数字,并且会与您的情况重叠

【讨论】:

    【解决方案2】:

    在您的约束下,检测毫秒时间戳是微不足道的。即使是过去一年的时间戳仍然比当前时间戳大。

    简单测试数字是否大于当前时间戳;如果是这样,你有一个以毫秒为单位的时间戳:

    now = time.mktime(time.gmtime())
    if t > now:
        # milliseconds, convert to seconds
        t /= 1000.0
    

    通过除以 1000,您可以将时间戳转换回以秒为单位的时间,并且可以应用默认的 time 模块函数。

    这是因为即使是表示过去一年的以毫秒为单位的时间戳,意外地被解释为 以秒为单位的时间戳,也会在未来很远

    >>> import time
    >>> ts = time.mktime(time.gmtime())
    >>> year_ago = ts - (86400 * 365)
    >>> time.gmtime(year_ago * 1000) # misinterpret milliseconds as seconds
    time.struct_time(tm_year=45395, tm_mon=7, tm_mday=9, tm_hour=14, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=190, tm_isdst=0)
    

    在混淆这两个范围之前,您必须有一个 1970 年初的时间戳

    >>> now = time.mktime(time.gmtime())
    >>> time.gmtime(ts / 1000) # misinterpret seconds as milliseconds
    time.struct_time(tm_year=1970, tm_mon=1, tm_mday=17, tm_hour=5, tm_min=25, tm_sec=13, tm_wday=5, tm_yday=17, tm_isdst=0)
    

    例如UNIX 纪元后前 17 天的时间戳可能与以毫秒为单位的时间戳混淆。该日期之后的所有内容都将大于“当前时间”时间戳。

    由于您的具体限制,您很幸运我们可以如此轻松地将两个单元分开。 更好的选择一开始就不要陷入这种情况。这些数据来自某个地方; 尽早确定您拥有什么数据类型,而不必稍后再猜测。没有系统会在某些时候随机给您以秒为单位的时间戳,而在其余时间以毫秒为单位的时间戳。当然,您可以根据其他信息知道您正在采购什么类型的数据,并在那时转换或注释您的数据以包含该类型?

    【讨论】:

    • 我可能遗漏了一些东西,但我认为您的意思是 t /= 1000.0 而不是 10.0 将秒转换为毫秒。
    • @cpburnz:哎呀,不,我错过了一些东西。更新中。
    • 在这个问题可以回答的范围内,你的方法是非常明智的,应该是公认的答案。话虽如此,我希望您补充“对数据来源​​的假设不能替代验证”。试图猜测时间单位是一个可怕的想法。 任何物理量都不应在没有单位的情况下进行交流。 其他任何事情都是糟糕的做法。只要记住the Mars climate orbiter blunder
    • @Floris:添加了关于尽早确定类型的警告。
    【解决方案3】:

    冒着被投反对票的风险,我想公开表示不要这样做。

    对物理量的单位进行假设是一个糟糕的想法——它导致Mars Meteorological Orbiter 的破坏(推力的计算单位为磅,发动机预计为牛顿。推力不足——轨道飞行器被烧毁在大气中)。

    如果您对数字的大小有一个很好的了解,您应该能够对单位做出“有根据的猜测”。例如,如果我告诉你我的体重是 230,你可以看着我并想“我打赌那是磅,而不是公斤”。同样,如果您将我生日的时间戳转换为日期,假设它以秒为单位,结果是 200 年后,您可以合理地假设“秒”是错误的单位。

    但这样做很危险。

    仍然 - 如果您必须这样做,那么总的来说,我会推荐以下方法:

    1. 考虑到所有可能的单位,将其转换为“合理”的比例(例如,将您的时间戳转换为年/月/日)。
    2. 查看您获得的值。其中哪一个是“最有可能”的。对于日期,您可能有一个好主意(这台计算机投入使用的日期:是 1970 年还是 2012 年?等等)
    3. 选择最有可能的值
    4. 在某处记录这是你所做的 - 这样如果这个决定的后果被证明是错误的,你可以追踪错误

    最后一点很重要——它能让你从错误中吸取教训。例如,如果你的时间戳告诉你彗星下次出现的时间,你可以打印

    彗星的下一次预期出现:2546 年 12 月 29 日(假设:X 的时间戳以秒为单位)

    这样,就有了一些“回来”。一般来说,“记录你的假设”不仅仅是好的建议 - 它在任何精确的科学中都是必不可少的。

    最后 - 时间戳从 ms 到 s 的转换是通过将数字除以 1000 来实现的。但我相信你知道这一点。

    【讨论】:

      【解决方案4】:

      马丁给出的答案的替代方案:

      当我们必须统一来自第 3 方的文档的时间戳时,我们遇到了这个问题。而之前的条件是:

      if date > time.time():
          use_miliseconds(date)
      else:
          use_seconds(date)
      

      ,它似乎应该可以工作,但有一些极端情况,特别是如果date 是从没有时区信息的字符串表示派生的,或者时钟正在更改。

      更安全的变体是使用:

      if date > time.time() + HUNDRED_YEARS:
          use_miliseconds(date)
      else:
          use_seconds(date)
      

      ,其中HUNDRED_YEARS = 100 * 365 * 24 * 3600。这种情况更容易出错,事实上,它适用于除 1970 年 1 月和 2 月之外的任何日期(无论哪种方式都是模棱两可的)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-24
        • 2023-03-11
        • 1970-01-01
        • 2015-06-17
        • 2017-06-12
        • 1970-01-01
        • 2011-08-02
        • 1970-01-01
        相关资源
        最近更新 更多