如何在 Garmin 设备中处理 timestamp_16?
how to handle timestamp_16 in Garmin devices?
我拥有一台 Garmin Vivosport,用于跟踪我的活动和睡眠,我想 运行 对我通过 Garmin Connect 下载的 FIT 文件中的心率数据进行一些分析。
问题是我没能正确对齐时间戳。
有人问了类似的问题here,但我没有找到答案,也无法评论以添加我的问题。
如 here 所述,在 FIT 文件中,时间戳信息分为两个不同的变量:一个 timestamp
不时出现,一个 timestamp_16
附加到每一个单独的测量。按照他们的说法,timestamp_16
包含了实际时间戳的低16位,所以应该和前面的timestamp
.
的高16位结合起来
我使用的是 2019 年 5 月 1 日记录的数据。文件涵盖一天的 24 小时,所以第一个数据点在 00:00(我在 Garmin Connect 的图形界面中检查过,一切都匹配) .在这个文件中,我发现这是第一个感兴趣的数据条目:
monitoring
* activity_type: sedentary
* current_activity_type_intensity: (8,)
* intensity: 0
* timestamp: 2019-04-30 22:00:00
[some other lines in between]
monitoring
* heart_rate: 72
* timestamp_16: 31132
上面截取的第一个 monitoring
对象是在包含心率的对象之前包含 timestamp
的最后一个对象,因此它与 linked 中的内容相匹配说明。
根据这些信息,我尝试了一些解决方案,但其中 none 我设法获得了文件中第一个数据点的实际时间戳,该时间戳为 2019 年 5 月 1 日的 00:00 (也不在几分钟之内)。
如果我按照上述 link 中给出的说明进行操作,我会得到:
mesgTimestamp = timestamp
mesgTimestamp += ( timestamp_16 - ( mesgTimestamp & 0xFFFF ) ) & 0xFFFF
但结果是:2019-05-01 12:49:00
我也尝试用timestamp_16
手动替换timestamp
的低16位,但还是没有成功:
timestamp : 0b1011100110010001011111001011000
timestamp_16 : 0b111100110011100
result : 0b1011100110010000111100110011100
上面result
对应的datetime
值为datetime.datetime(2019, 4, 30, 18, 36, 44)
.
Here 是我所有尝试的代码。
Here 是一个正在讨论的 github 问题。
正如你在上面看到的,我无法得到正确的结果,即 2019 年 5 月 1 日 00:00。除此之外,如果我在位级别手动应用 Garmin 的配方,与我应用他们给出的公式得到的结果相比,我得到的结果不同。
此外,我得到的结果与非零分秒的时间相差很大,这让我相信这不是时区问题(我也尝试过但没有成功) .
有没有人找到一个稳定的解决方案?如果你有的话,能否请你分享一些东西(也有其他语言的,我对这里的逻辑感兴趣)?
几个月来我一直在努力把这件事做好(在我的业余时间做这件事),但这种缺乏结果真的令人沮丧:\
考虑到特殊的 Garmin 纪元,它比 Unix 时间戳纪元晚了 631065600 秒,计算需要在那个特殊的时间进行(如果只是一个正常的偏移量就不会这样,但是这些偏移量不是严格相加的,因此时间的 "absolute value" 很重要)。只需减去 631065600:
dt_offset = datetime.datetime(2019,4,30,22,0,0,0)
timestamp = int(datetime.datetime.timestamp(dt_offset)) - 631065600
timestamp_16 = 31132
以任何合理的方式应用时间增量,例如:
mesgTimestamp = timestamp
mesgTimestamp += ( timestamp_16 - ( mesgTimestamp & 0xFFFF ) ) & 0xFFFF
或者:
mesgTimestamp = timestamp + ((timestamp_16 - timestamp) & 0xffff)
或者:
mesgTimestamp = (timestamp & 0xffff0000) | timestamp_16
if mesgTimestamp < timestamp:
mesgTimestamp += 0x10000
使用生成的时间戳时再次应用 Garmin 纪元偏移量:
print('New:', datetime.datetime.fromtimestamp(mesgTimestamp + 631065600, pytz.timezone('Europe/Zurich')))
结果:New: 2019-05-01 00:01:00+02:00
够接近了吗?
我拥有一台 Garmin Vivosport,用于跟踪我的活动和睡眠,我想 运行 对我通过 Garmin Connect 下载的 FIT 文件中的心率数据进行一些分析。
问题是我没能正确对齐时间戳。
有人问了类似的问题here,但我没有找到答案,也无法评论以添加我的问题。
如 here 所述,在 FIT 文件中,时间戳信息分为两个不同的变量:一个 timestamp
不时出现,一个 timestamp_16
附加到每一个单独的测量。按照他们的说法,timestamp_16
包含了实际时间戳的低16位,所以应该和前面的timestamp
.
我使用的是 2019 年 5 月 1 日记录的数据。文件涵盖一天的 24 小时,所以第一个数据点在 00:00(我在 Garmin Connect 的图形界面中检查过,一切都匹配) .在这个文件中,我发现这是第一个感兴趣的数据条目:
monitoring
* activity_type: sedentary
* current_activity_type_intensity: (8,)
* intensity: 0
* timestamp: 2019-04-30 22:00:00
[some other lines in between]
monitoring
* heart_rate: 72
* timestamp_16: 31132
上面截取的第一个 monitoring
对象是在包含心率的对象之前包含 timestamp
的最后一个对象,因此它与 linked 中的内容相匹配说明。
根据这些信息,我尝试了一些解决方案,但其中 none 我设法获得了文件中第一个数据点的实际时间戳,该时间戳为 2019 年 5 月 1 日的 00:00 (也不在几分钟之内)。
如果我按照上述 link 中给出的说明进行操作,我会得到:
mesgTimestamp = timestamp
mesgTimestamp += ( timestamp_16 - ( mesgTimestamp & 0xFFFF ) ) & 0xFFFF
但结果是:2019-05-01 12:49:00
我也尝试用timestamp_16
手动替换timestamp
的低16位,但还是没有成功:
timestamp : 0b1011100110010001011111001011000
timestamp_16 : 0b111100110011100
result : 0b1011100110010000111100110011100
上面result
对应的datetime
值为datetime.datetime(2019, 4, 30, 18, 36, 44)
.
Here 是我所有尝试的代码。 Here 是一个正在讨论的 github 问题。
正如你在上面看到的,我无法得到正确的结果,即 2019 年 5 月 1 日 00:00。除此之外,如果我在位级别手动应用 Garmin 的配方,与我应用他们给出的公式得到的结果相比,我得到的结果不同。
此外,我得到的结果与非零分秒的时间相差很大,这让我相信这不是时区问题(我也尝试过但没有成功) .
有没有人找到一个稳定的解决方案?如果你有的话,能否请你分享一些东西(也有其他语言的,我对这里的逻辑感兴趣)?
几个月来我一直在努力把这件事做好(在我的业余时间做这件事),但这种缺乏结果真的令人沮丧:\
考虑到特殊的 Garmin 纪元,它比 Unix 时间戳纪元晚了 631065600 秒,计算需要在那个特殊的时间进行(如果只是一个正常的偏移量就不会这样,但是这些偏移量不是严格相加的,因此时间的 "absolute value" 很重要)。只需减去 631065600:
dt_offset = datetime.datetime(2019,4,30,22,0,0,0)
timestamp = int(datetime.datetime.timestamp(dt_offset)) - 631065600
timestamp_16 = 31132
以任何合理的方式应用时间增量,例如:
mesgTimestamp = timestamp
mesgTimestamp += ( timestamp_16 - ( mesgTimestamp & 0xFFFF ) ) & 0xFFFF
或者:
mesgTimestamp = timestamp + ((timestamp_16 - timestamp) & 0xffff)
或者:
mesgTimestamp = (timestamp & 0xffff0000) | timestamp_16
if mesgTimestamp < timestamp:
mesgTimestamp += 0x10000
使用生成的时间戳时再次应用 Garmin 纪元偏移量:
print('New:', datetime.datetime.fromtimestamp(mesgTimestamp + 631065600, pytz.timezone('Europe/Zurich')))
结果:New: 2019-05-01 00:01:00+02:00
够接近了吗?