将二进制64位时间戳偏移从GPS时期转换为python datetime对象

时间:2012-10-10 07:56:31

标签: python datetime binary

我正在试图找出我认为应该是8字节/ 64位时间戳的内容。

import datetime
GPS_EPOCH = datetime.datetime(1980, 1, 6)
t1 = "\x00\x00\xBF\x13\xDB\x79\xC0\x00" # expected: 2012-10-04 01:00:51.759
t2 = "\x00\x00\xC0\x13\xDB\x79\xC0\x00" # expected: 2012-10-04 01:00:51.760
t3 = "\x00\x00\xC2\x13\xDB\x79\xC0\x00" # expected: 2012-10-04 01:00:51.763
t4 = "\x00\x00\x80\xE7\xFB\x79\xC0\x00" # expected: 2012-10-04 01:45:40.960

我认为t1t2产生的值(s?)应该偏离GPS_EPOCH。 但是,我似乎无法得到与预期结果datetime匹配的结果。

我一直在阅读,这似乎是合乎逻辑的,它将被分成两部分,一部分可能是小数,另一部分是秒(每个4字节?)。但是,我没有找到任何基于GPS纪元的时间戳格式的参考。

任何想法如何将其转化为预期结果?

3 个答案:

答案 0 :(得分:8)

我拥有它。你提供了足够的例子。

>>> t1 = "\x00\x00\xBF\x13\xDB\x79\xC0\x00" # expected: 2012-10-04 01:00:51.759
>>> import struct
>>> import datetime
>>> GPS_EPOCH = datetime.datetime(1980, 1, 6)
>>> t1_unpacked = struct.unpack('<q', t1)[0]
>>> t1_seconds = t1_unpacked / 52428800
>>> t1_us = int(round((t1_unpacked % 52428800) / 52.428800, 0))
>>> GPS_EPOCH + datetime.timedelta(seconds=t1_seconds, microseconds=t1_us)
datetime.datetime(2012, 10, 4, 1, 0, 51, 758750)

全部放在一起:

def gps_time(timestamp):
    unpacked = struct.unpack('<q', timestamp)[0]
    seconds = unpacked / 52428800
    microseconds = int(round((unpacked % 52428800) / 52.428800, 0))
    return GPS_EPOCH + datetime.timedelta(seconds=seconds, microseconds=microseconds)

>>> gps_time(t2)
datetime.datetime(2012, 10, 4, 1, 0, 51, 760000)
>>> gps_time(t3)
datetime.datetime(2012, 10, 4, 1, 0, 51, 762500)
>>> gps_time(t4)
datetime.datetime(2012, 10, 4, 1, 45, 40, 960000)

答案 1 :(得分:2)

您可以使用标准库的struct模块查看您的8个字节是否编码64位整数:

>>> import struct
>>> number = struct.unpack('q', "\x00\x00\xBF\x13\xDB\x79\xC0\x00")
>>> "{:,}".format(number)
'54,177,177,364,529,152'

这是一个非常大的整数!但它与您列出的时代有关吗?可能不是......

也许它不是整数。我有一个我一直在玩的原始GPS模块,它的数据在NMEA语句中是连续的。您可以在线找到format information for those

答案 2 :(得分:1)

<强> EDITED

抱歉,这不是一个解决方案,只有一些起点,如果其他人有更多时间深入了解。

第一个日期存储的“隐藏”号码应为:

import datetime
from datetime import datetime, timedelta
GPS_EPOCH = datetime(1980, 1, 6)
date_1 = datetime(2012,10,04, 01,00,51,759)
d=(date_1 - GPS_EPOCH)
( d.days * 24 * 60 * 60 + d.seconds ) * 1000 + d.microseconds

---->   1.033.347.651.759   <----

但是你解压缩第一个数据十六进制代码的数字是:

struct.unpack('q', "\xBF\x13\xDB\x79\xC0\x00\x00\x00" )[0]

---->     826.678.121.407   <----

请注意,我将\ xBF移动到最低有效数字位置。我这样做是因为你的样本1毫秒是\ xC0 - \ xBF。在第一个样本中,最低有效数字似乎是\ xBF。

然后,对于您的数据样本,公式可以是:

 milliseconds =  ( 1033347651759 - 826678121407 ) +  unpack_your_string_with_offset
 GPS_EPOCH + milliseconds

使用较少的数据进行测试......

>>> milliseconds =  ( 1033347651759 - 826678121407 ) + \ 
                    struct.unpack('q', "\xBF\x13\xDB\x79\xC0\x00\x00\x00" )[0]
>>> 
>>> GPS_EPOCH + timedelta( milliseconds = milliseconds)
datetime.datetime(2012, 10, 4, 1, 0, 51, 759000)

发布更多数据样本和预期结果以检查或推断新公式。

我从@leon_matthews采取了解包方法:+1;)

我希望有些Raiman家伙能找到解决方案。我会按照你的回答。