
本教程详细介绍了如何将特定格式的二进制数据转换为精确的日期时间戳。通过对二进制模式的深入分析,我们发现了一种基于字节提取、反转、位移和常数偏移的转换方法。文章提供了python实现代码,并利用pandas库处理时区和验证转换结果,旨在帮助读者理解和解决类似二进制时间戳解析问题。
在数据处理领域,我们经常会遇到需要解析非标准格式二进制数据的情况,其中将二进制编码的时间戳转换为可读的日期时间是一个常见挑战。本教程将引导您完成一个具体的案例,展示如何通过模式识别、位操作和Python编程,将一组特定的二进制字节序列转换为准确的日期时间对象。
我们面对的二进制数据格式如下所示(以十六进制表示),其中每个序列都对应一个特定的日期时间:
30 65 1a eb e3 f2 96 c5 41 -- 对应 2023年12月16日 15:03 30 c6 36 85 70 8a 97 c5 41 -- 对应 2023年12月17日 12:37 30 4a 26 1b 6b 29 74 c4 41 -- 对应 2022年10月1日 12:49
通过观察这些样本,我们可以发现一些关键模式:
这些观察提示我们,需要关注中间的7个字节,并尝试将其解释为一个随时间变化的数值。
立即学习“Python免费学习笔记(深入)”;
经过进一步的实验和分析,我们发现了一个有效的转换路径:
我们将上述逻辑封装在一个Python函数 f(k) 中:
def f(k):
"""
将二进制字符串中的核心字节转换为一个基于Epoch的近似秒数。
Args:
k (str): 包含十六进制字节的字符串,例如 '30 65 1a eb e3 f2 96 c5 41'。
Returns:
int: 转换后的近似Epoch秒数。
"""
# 1. 移除第一个和最后两个字节,并反转剩余字节的顺序
# k.split()[1:-1] 得到 ['65', '1a', 'eb', 'e3', 'f2', '96', 'c5']
# [::-1] 反转为 ['c5', '96', 'f2', 'e3', 'eb', '1a', '65']
# ''.join(...) 拼接成 'c596f2e3eb1a65'
# 2. 将十六进制字符串转换为整数
# 3. 右移23位
# 4. 减去经验常数偏移
return (int(''.join(k.split()[1:-1][::-1]), 16) >> 23) - 4927272860在时间戳转换中,时区是一个不可忽视的因素。原始数据中2022年10月的日期与预期结果存在3600秒(1小时)的误差,这强烈暗示了夏令时(DST)的影响。因此,在将Epoch秒数转换为具体的日期时间对象时,我们需要指定正确的时区。
为了实现健壮的日期时间处理,我们推荐使用 pandas 库,它提供了强大的 Timestamp 对象和时区管理功能。
import pandas as pd
# 定义目标时区,根据数据来源地选择
tz = 'Europe/Zurich' # 假设数据来自欧洲/苏黎世时区
def to_time(k, tz):
"""
将二进制字符串转换为带有时区信息的pandas Timestamp对象。
Args:
k (str): 包含十六进制字节的字符串。
tz (str): 目标时区字符串,例如 'Europe/Zurich'。
Returns:
pandas.Timestamp: 转换后的带有时区信息的日期时间对象。
"""
# f(k) 返回的是Epoch秒数
# pd.Timestamp 默认接收纳秒级时间戳,所以需要乘以 1e9
return pd.Timestamp(f(k) * 1e9, tz=tz)
# 示例数据及对应的参考时间
examples = {
'30 65 1a eb e3 f2 96 c5 41': '16 December 2023 at 15:03',
'30 c6 36 85 70 8a 97 c5 41': '17 December 2023 at 12:37',
'30 4a 26 1b 6b 29 74 c4 41': '1 October 2022 at 12:49',
'30 23 84 b1 a8 b5 97 c5 41': '17 December 2023 at 18:45',
'30 3f 91 e7 96 b5 97 c5 41': '17 December 2023 at 18:45:30',
'30 a6 d6 2f d1 b5 97 c5 41': '17 December 2023 at 18:46',
'30 e8 16 9c b9 b5 97 c5 41': '17 December 2023 at 18:47',
}
# 将参考时间转换为带有时区信息的pandas Timestamp对象,并按时间排序
examples = dict(sorted([
(k, pd.Timestamp(v, tz=tz)) for k, v in examples.items()
], key=lambda item: item[1]))为了验证转换的准确性,我们可以将计算出的时间与原始参考时间进行对比,并计算它们之间的秒数差。
fmt = '%F %T %Z' # 定义日期时间格式化字符串
test_results = [
(
f'{v:{fmt}}', # 参考时间
f'{to_time(k, tz=tz):{fmt}}', # 估算时间
(to_time(k, tz=tz) - v).total_seconds(), # 差异(秒)
)
for k, v in examples.items()
]
# 打印测试结果
for result in test_results:
print(f"参考时间: {result[0]}, 估算时间: {result[1]}, 差异 (秒): {result[2]}")运行上述代码,您将看到类似以下的结果:
参考时间: 2022-10-01 12:49:00 CEST, 估算时间: 2022-10-01 12:49:30 CEST, 差异 (秒): 30.0 参考时间: 2023-12-16 15:03:00 CET, 估算时间: 2023-12-16 15:03:23 CET, 差异 (秒): 23.0 参考时间: 2023-12-17 12:37:00 CET, 估算时间: 2023-12-17 12:36:37 CET, 差异 (秒): -23.0 参考时间: 2023-12-17 18:45:00 CET, 估算时间: 2023-12-17 18:45:25 CET, 差异 (秒): 25.0 参考时间: 2023-12-17 18:45:30 CET, 估算时间: 2023-12-17 18:44:49 CET, 差异 (秒): -41.0 参考时间: 2023-12-17 18:46:00 CET, 估算时间: 2023-12-17 18:46:46 CET, 差异 (秒): 46.0 参考时间: 2023-12-17 18:47:00 CET, 估算时间: 2023-12-17 18:45:59 CET, 差异 (秒): -61.0
从结果可以看出,转换后的时间与参考时间之间存在数十秒的差异。这表明当前的常数偏移 4927272860 只是一个近似值,可能需要根据更多的样本数据进行微调,以达到更高的精度。
本教程展示了如何通过逆向工程和Python编程,将一种特定的二进制时间戳格式转换为可读的日期时间。关键步骤包括:识别并提取核心数据字节、反转字节顺序、进行位移操作、以及应用一个经验性的常数偏移来校准到Unix Epoch时间。同时,我们强调了使用 pandas 处理时区的重要性,以确保日期时间的准确性和健壮性。
虽然当前的转换方法能提供相当准确的结果,但若要达到完美匹配,可能需要更多的数据样本来精确调整位移常数和偏移量。在实际应用中,这种方法为解析未知或专有二进制时间戳提供了一个强大的起点。
以上就是Python二进制数据到日期时间戳的转换教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号