如何测试给定的时间戳是以秒还是毫秒为单位?

时间:2014-05-29 08:39:42

标签: python datetime timestamp unix-timestamp

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

例如:

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

更新:我明白在不给出一些限制的情况下无法判断,所以这就是

  • current_ts - 86400 * 365<未知< current_ts

Assume current_ts = current unix timestamp

4 个答案:

答案 0 :(得分:40)

如果convert最大时间戳值为x位数(毫秒),则会得到如下内容:

  • 9999999999999(13位数字)指Sat Nov 20 2286 17:46:39 UTC
  • 999999999999(12位数字)表示Sun Sep 09 2001 01:46:39 UTC
  • 99999999999(11位数字)指Sat Mar 03 1973 09:46:39 UTC

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

  • 1000000000000000(16位)意味着Fri Sep 27 33658 01:46:40但到那时我将生活在Alpha Centauri系统的行星上,时间标准可能会有所改变:)

P.S。如果您的时间戳不能超过1973年,您可以将条件放宽至12位或更多。条件应该只有在以下情况下才能完成:

  • 100000000000000(15位数)表示Wed Nov 16 5138 09:46:40 因为这在几秒钟内将有12位数字,并将与您的条件重叠

答案 1 :(得分:20)

冒着吸引挫折的风险,我想记录在案,说不要做。

对物理量的单位做出假设是一个可怕的想法 - 它导致了Mars Meteorological Orbiter的破坏(计算的推力单位是磅,引擎预计牛顿。没有足够的推力 - 和轨道飞行器在大气中燃烧。)

如果你对数字的大小非常了解,你应该能够对这些单位进行“有根据的猜测”。例如,如果我告诉你我的体重是230,你可以看着我,然后想“我打赌这是磅,而不是公斤”。同样,如果你将我生日的时间戳转换为假设的日期,以秒为单位,并且结果是将来200年,你可以合理地假设“秒”是错误的单位。

但这是一件危险的事情。

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

  1. 鉴于所有可能的单位,将转换为“合理”的比例(例如,将时间戳转换为年/月/日)。
  2. 查看您获得的值。其中哪一个“最有可能”。在日期的情况下,您可能有一个好主意(计算机投入使用的日期:是1970年还是2012年?等)
  3. 选择最有可能的值
  4. 记录某处这就是你所做的 - 所以如果这个决定的结果是错误的,你可以追踪错误
  5. 最后一件事很重要 - 它可以让你从错误中吸取教训。例如,如果您的时间戳告诉您下次出现彗星的时间,您可以打印

      彗星的下一个预期出现:2546年12月29日(假设:X的时间戳是在几秒钟内给出的)

    通过这种方式,有一些“回来”。一般来说,“记录您的假设”不仅仅是一个好建议 - 它对于任何精确的科学都是必不可少的。

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

答案 2 :(得分:16)

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

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

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)

E.g。 UNIX纪元之后的前17天中的时间戳可能会混淆时间戳(以毫秒为单位)。 之后的所有内容都将大于“当前时间”时间戳。

根据您的具体限制,您很幸运我们可以轻松地将两个单元分开。 更好的选项是首先没有进入这种情况 。这些数据来自某个地方;尽可能早地确定 您拥有的数据类型,而不必在以后猜测。没有系统会在某些时间以秒为单位随机给您时间戳,其余时间以毫秒为单位的时间戳。当然,您可以根据其他信息了解您采购的数据类型,并在当时转换或注释您的数据以包含类型?

答案 3 :(得分:0)

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

当我们不得不统一来自第三方的文档的时间戳时,我们遇到了这个问题。而先前的条件是:

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 = 365 * 24 * 3600。这种情况更容易出错,实际上,它适用于除1970年1月和2月之外的任何日期(这两种方式都不明确)。