You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 09:47:41