C++11中将Boost时间API替换为std::chrono的方法及问题排查
原问题解答
1. boost::posix_time::ptime myTime(boost::gregorian::date(1960, 1, 1)) 的C++11替代方案
C++11标准库无内置日历支持,需通过计算目标日期与Unix纪元(1970-01-01 UTC)的时间差构造std::chrono::time_point:
// 1960-01-01到1970-01-01共3653天(含2个闰年) constexpr auto days_since_epoch = -3653; // 转换为微秒级时长(可按需调整精度) auto epoch_offset = std::chrono::days(days_since_epoch); // 构造目标时间点 auto myTime = std::chrono::system_clock::from_time_t(0) + epoch_offset;
注:手动计算日期差需注意闰年、月份天数,若需更可靠的日历逻辑,可临时引入轻量第三方兼容库,或硬编码已知偏移量。
2. boost::posix_time::microsec_clock 相关方法的替代
microsec_clock::universal_time():直接用std::chrono::system_clock::now()替代,system_clock的基准为UTC,多数平台支持微秒级精度。microsec_clock::local_time():C++11无标准本地时钟API,需手动转换UTC时间到本地时间:
auto utc_now = std::chrono::system_clock::now(); // 提取UTC时间的time_t和亚秒部分 time_t utc_t = std::chrono::system_clock::to_time_t(utc_now); auto subsec = utc_now - std::chrono::system_clock::from_time_t(utc_t); // 转换为本地时间的time_t tm local_tm = *std::localtime(&utc_t); time_t local_t = std::mktime(&local_tm); // 构造带亚秒精度的本地时间点 auto local_now = std::chrono::system_clock::from_time_t(local_t) + subsec;
high_resolution_clock不能替代:它用于短间隔计时,不保证与系统时间(UTC/本地时间)同步,不同平台实现可能关联system_clock或steady_clock。
3. boost::posix_time::time_duration 的替代方案
直接使用std::chrono::duration模板类,标准库提供常用精度别名:
- 微秒:
std::chrono::microseconds - 毫秒:
std::chrono::milliseconds - 秒:
std::chrono::seconds - 自定义精度:例如
std::chrono::duration<long long, std::micro>(等价于microseconds)
示例:
// 替代boost::posix_time::milliseconds(500) auto duration = std::chrono::milliseconds(500); // 计算操作耗时 auto start = std::chrono::system_clock::now(); // ... 执行操作 ... auto elapsed = std::chrono::system_clock::now() - start;
4. boost::system_time const timeout = boost::get_system_time() 的替代
直接替换为std::chrono::system_clock::now(),但该timeout用于Boost线程API(如condition_variable)时会因类型不兼容报错,解决方法见下文。
补充编译错误处理
将std::chrono::time_point传入Boost线程API时,需转换为Boost期望的boost::system_time(本质是boost::posix_time::ptime):
// 获取std时间点 auto std_now = std::chrono::system_clock::now(); // 转换为time_t time_t t = std::chrono::system_clock::to_time_t(std_now); // 转为boost::ptime(即system_time) boost::posix_time::ptime timeout = boost::posix_time::from_time_t(t); // 补充亚秒精度 auto subsec = std_now - std::chrono::system_clock::from_time_t(t); timeout += boost::posix_time::microseconds( std::chrono::duration_cast<std::chrono::microseconds>(subsec).count() );
使用Boost 1.59+版本可直接通过boost::chrono桥接std::chrono类型,无需手动转换。
额外疑问解答
1. boost::posix_time::microsec_clock::universal_time() 转std::chrono是否必须用system_clock?
是。C++11标准中仅std::chrono::system_clock与系统UTC时间绑定,steady_clock用于单调计时(不受系统时间调整影响),high_resolution_clock精度最高但不保证与系统时间同步,因此必须用system_clock::now()替代。
2. 两行特定代码的C++11转换
boost::posix_time::ptime time_t_epoch(boost::gregorian::date(1970,1,1)):
直接用Unix纪元零点转换:auto time_t_epoch = std::chrono::system_clock::from_time_t(0);boost::posix_time::microsec_clock::local_time():
使用前文UTC转本地时间的逻辑,完整封装示例:auto get_local_time() { auto utc_now = std::chrono::system_clock::now(); time_t utc_t = std::chrono::system_clock::to_time_t(utc_now); auto subsec = utc_now - std::chrono::system_clock::from_time_t(utc_t); tm local_tm = *std::localtime(&utc_t); time_t local_t = std::mktime(&local_tm); return std::chrono::system_clock::from_time_t(local_t) + subsec; }
内容的提问来源于stack exchange,提问作者user1584421

