如何用std::chrono/date库正确添加日历日?含时区处理
问题解答
现有实现的正确性
你的代码最终能得到正确结果,但存在不够优雅的地方:当对June/30/2023的日期加1天时,会生成无效的year_month_day(6月没有31天),此时ymd.ok() == false。不过后续通过sys_days{ymd}转换时,chrono库会自动将无效日期调整为下一个有效日期(即2023-07-01),所以最终结果是正确的,但中间的无效日期状态可能在其他场景下引发问题(比如需要校验日期合法性时)。
更简便的写法
UTC场景(无时区)
无需手动拆分year_month_day,直接将时间点拆分为日期部分和当日时间部分,对日期部分加1天后再拼接时间即可:
#include <chrono> #include <date/date.h> using namespace std::chrono; using namespace date; int main() { // 原始时间点 system_clock::time_point tp = sys_days{June / 30 / 2023} + 22h + 35min + 10s; // 拆分日期和当日时间 sys_days yd = floor<days>(tp); auto tod = tp - yd; // 加一个日历日 tp = yd + days{1} + tod; return 0; }
如果使用C++20及以上版本,还可以用split函数简化拆分步骤:
auto [yd, tod] = split(tp); tp = yd + days{1} + tod;
本地化场景(带时区)
直接操作本地时间更清晰,能避免不必要的时区转换开销:
#include <chrono> #include <date/tz.h> using namespace std::chrono; using namespace date; int main() { auto loc = locate_zone("Europe/Rome"); // 构造本地时间并直接加1个日历日 local_seconds lt = local_days{June / 30 / 2023} + days{1} + 22h + 35min + 10s; // 转换为带时区的时间 zoned_time<seconds> tz{loc, lt}; return 0; }
能否跳过创建tp直接得到zoned_time?
完全可以,直接将加完日历日的本地时间传入zoned_time构造函数即可,一步到位:
auto loc = locate_zone("Europe/Rome"); zoned_time<seconds> tz{ loc, local_days{June / 30 / 2023} + days{1} + 22h + 35min + 10s };
内容的提问来源于stack exchange,提问作者HumbleProgrammer
相关产品推荐
相关产品推荐

