如何用C++20 std::chrono正确获取当前本地工作日?
C++20 std::chrono 获取本地工作日的问题解答
问题背景
尝试使用C++20的std::chrono打印当前本地时间对应的工作日,参考示例代码如下:
#include <chrono> #include <iostream> int main() { using namespace std::chrono; system_clock::time_point now = system_clock::now(); // system_clock::time_point now = sys_days{June / 26d / 2023y} + 12h; weekday wd{floor<days>(now)}; #ifdef _WIN32 std::cout << wd << "\n"; #else std::cout << wd.c_encoding() << " (Sunday = " << Sunday.c_encoding() << ")\n"; #endif return 0; }
运行后输出为Tue,但实际当天是周一;若注释掉system_clock::now(),改用手动定义的2023年6月26日(发布问题当天,时区-0400),则输出正确的Mon。后续尝试修改代码处理时区问题,但编译报错:
#include <chrono> #include <iostream> int main() { using namespace std::chrono; auto now = std::chrono::system_clock::now(); auto now_local = zoned_time{current_zone(), now}.get_local_time(); sys_days now_local_in_days{floor<days>(now_local)}; // !!! no constructor available weekday wd{now_local_in_days}; #ifdef _WIN32 std::cout << wd << "\n"; #else std::cout << wd.c_encoding() << "\n"; #endif return 0; }
报错点为sys_days now_local_in_days{floor<days>(now_local)};,提示无可用构造函数。
问题1:如何正确获取当前日期对应的本地工作日?
核心是将UTC时间转换为本地时区的日期,再提取工作日。正确代码如下:
#include <chrono> #include <iostream> int main() { using namespace std::chrono; // 获取当前UTC时间点 auto now = system_clock::now(); // 转换为本地时区的时间 zoned_time local_now{current_zone(), now}; // 提取本地日期的天级精度时间点 local_days local_today{floor<days>(local_now.get_local_time())}; // 从本地日期构造工作日 weekday wd{local_today}; #ifdef _WIN32 std::cout << wd << "\n"; #else std::cout << wd.c_encoding() << "\n"; #endif return 0; }
问题2:为何now()获取的日期与sys_days/year_month_day定义的日期表现不同?
system_clock::now()获取的是UTC时间,floor<days>(now)得到的是UTC时区的当天日期。- 你的本地时区为-0400(比UTC晚4小时),如果当前UTC时间已经进入次日凌晨(比如UTC 00:00-04:00),本地时间仍处于前一天的20:00-24:00。此时
floor<days>(now)取的是UTC的次日日期,导致工作日计算错误。 - 手动定义的
sys_days{June / 26d / 2023y}是UTC时区的2023年6月26日,加上12小时后,对应本地时区是6月26日8点,此时UTC和本地日期一致,所以工作日计算正确。
问题3:如何将local_time转换为weekday?
local_time是无时区信息的本地时间,不能直接转换为sys_days(sys_days是UTC时区的天级时间点)。正确做法是:
- 用
floor<days>(local_time)获取本地时间的天级精度时间点,类型为local_time<days>(别名local_days)。 - 直接用
local_days构造weekday,因为weekday支持从任何天级精度的时间点(包括local_days)初始化。
示例代码片段:
auto local_t = local_days{floor<days>(now_local)}; weekday wd{local_t};
内容的提问来源于stack exchange,提问作者MHebes
相关产品推荐
相关产品推荐

