如何将libgpiod事件的std::chrono::nanoseconds时间戳转为Linux纪元时间
如何将libgpiod v1事件的单调时间戳转换为Linux纪元时间?
问题根源
libgpiod v1返回的事件时间戳是系统启动以来的单调时间(对应Linux的CLOCK_MONOTONIC时钟),而非Unix纪元(1970-01-01 00:00:00 UTC)时间。你之前的代码仅将单调时间转换为秒数,得到的是系统启动后流逝的时长,自然不是纪元时间。
解决方案思路
要得到事件的纪元时间,需要先计算单调时间与纪元时间的偏移量,再将事件的单调时间加上该偏移量:
- 程序运行时,获取当前的单调时间和纪元时间,计算两者差值(偏移量 = 当前纪元时间 - 当前单调时间)
- 用事件的单调时间戳加上偏移量,得到事件发生时的纪元时间
代码实现
1. 计算单调时间与纪元时间的偏移量
#include <chrono> #include <ctime> // 计算CLOCK_MONOTONIC到Unix纪元的时间偏移(只需初始化一次) std::chrono::nanoseconds get_monotonic_epoch_offset() { // steady_clock对应Linux的CLOCK_MONOTONIC时钟 auto now_monotonic = std::chrono::steady_clock::now().time_since_epoch(); // system_clock对应Unix纪元时间 auto now_epoch = std::chrono::system_clock::now().time_since_epoch(); // 返回偏移量:纪元时间 - 单调时间 return now_epoch - now_monotonic; }
2. 转换事件时间戳为纪元时间
unsigned long State::convert_timestamp_to_epoch(std::chrono::nanoseconds event_timestamp) { // 静态存储偏移量,程序启动时计算一次 static const auto offset = get_monotonic_epoch_offset(); // 事件的纪元时间 = 事件单调时间 + 偏移量 auto event_epoch_ns = event_timestamp + offset; // 转换为秒级纪元时间 auto event_epoch_sec = std::chrono::duration_cast<std::chrono::seconds>(event_epoch_ns); return static_cast<unsigned long>(event_epoch_sec.count()); }
注意事项
- 偏移量默认只需在程序启动时计算一次,因为
steady_clock的单调时间不受系统时间修改影响。但如果系统时间可能被手动调整(如NTP校准、手动修改时间),则需要定期重新计算偏移量,否则转换结果会不准确。 - 如果需要更精确的时间(如毫秒/微秒级),只需将
duration_cast的目标类型换成对应的chrono时长即可(例如std::chrono::milliseconds)。
内容的提问来源于stack exchange,提问作者Mendes
相关产品推荐
相关产品推荐

