在这里插入图片描述

📚 目录

一、C语言时代的日期处理:<ctime>

早期C++主要沿用C语言的时间接口,定义在头文件 <ctime> 中。
其核心结构是 std::time_t(自1970年1月1日以来的秒数)与 std::tm(本地时间结构体)。

1. 获取当前时间

#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>

int main() {
    std::time_t now = std::time(nullptr);  // 获取当前时间(自1970-01-01起的秒数)
    std::cout << "time_t: " << now << std::endl;

    // 转换为本地时间
    std::tm* localTime = std::localtime(&now);
    std::cout << "Local time: "
              << 1900 + localTime->tm_year << "-"
              << 1 + localTime->tm_mon << "-"
              << localTime->tm_mday << " "
              << localTime->tm_hour << ":"
              << localTime->tm_min << ":"
              << localTime->tm_sec << std::endl;

    return 0;
}

输出示例:

在这里插入图片描述

error C4996: ‘localtime’: This function or variable may be unsafe.
Consider using localtime_s instead.
To disable deprecation, use _CRT_SECURE_NO_WARNINGS.

是 Visual Studio 的安全警告机制(Secure CRT) 发出的,
它认为 localtime() 是不安全的(因为它返回的 tm* 指向全局静态对象,可能线程不安全)。

2. 使用更安全的 localtime_s()

#include <ctime>
#include <iostream>

int main() {
    std::time_t now = std::time(nullptr);

    std::tm localTime{};
    localtime_s(&localTime, &now);  // ✅ 安全版本

    std::cout << "Local time: "
              << 1900 + localTime.tm_year << "-"
              << 1 + localTime.tm_mon << "-"
              << localTime.tm_mday << " "
              << localTime.tm_hour << ":"
              << localTime.tm_min << ":"
              << localTime.tm_sec << std::endl;

    return 0;
}

💡 localtime_s 的参数顺序是:
int localtime_s(struct tm* _Tm, const time_t* _Time);
注意与 POSIX 的 localtime_r() 参数顺序相反!

输出示例:
在这里插入图片描述

3. 结构体 std::tm 解析

字段含义示例
tm_year年份偏移量(从1900开始)125 → 2025
tm_mon月份,从0开始0~11
tm_mday日(1~31)10
tm_hour时(0~23)23
tm_min分(0~59)28
tm_sec秒(0~59)14

因此,格式化时常常要加上 19001 修正。

4. 时间字符串与格式化

char buffer[64];
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localTime);
std::cout << "Formatted time: " << buffer << std::endl;

输出:

Formatted time: 2025-10-10 23:28:14

缺点:

  • 容易出错(结构体字段不直观)
  • 不支持毫秒、纳秒
  • 不便于时间计算

二、现代C++的时间库:<chrono>

C++11 引入的 <chrono> 库带来了强类型时间系统。
它更安全、更精确,也更符合现代开发习惯。

1. 获取当前时间

#define _CRT_SECURE_NO_WARNINGS
#include <chrono>
#include <iostream>

int main() {
    auto now = std::chrono::system_clock::now();
    std::time_t t = std::chrono::system_clock::to_time_t(now);
    std::cout << "Current time: " << std::ctime(&t);
}

输出:

在这里插入图片描述

2. 高精度时间点与持续时间

#include <chrono>
#include <iostream>
#include <thread>

int main() {
    auto start = std::chrono::steady_clock::now();

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

    std::cout << "Elapsed: " << duration.count() << " ms\n";
}

输出:

在这里插入图片描述

steady_clock 单调递增,不受系统时间调整影响,适合用于性能测试。

3. 时间单位与类型系统

using namespace std::chrono_literals;

auto delay = 2s + 500ms;
std::cout << delay.count() << " milliseconds total\n";

输出:

在这里插入图片描述

单位类型名
std::chrono::seconds
毫秒std::chrono::milliseconds
微秒std::chrono::microseconds
纳秒std::chrono::nanoseconds

4. 日期与格式化输出(C++20)

C++20 新增了日期类型与格式化支持:
在这里插入图片描述

#include <chrono>
#include <iostream>
#include <format>

int main() {
    using namespace std::chrono;

    auto now = system_clock::now();
    auto today = floor<days>(now);
    year_month_day ymd{today};

    std::cout << std::format("Today is: {:%Y-%m-%d}\n", ymd);
}

输出:

在这里插入图片描述

日期加减也更直观:

auto tomorrow = sys_days{ ymd } + days{ 1 };
std::cout << std::format("Tomorrow: {:%Y-%m-%d}\n", tomorrow);

在这里插入图片描述


三、实战:计算两个日期的差值

#include <chrono>
#include <iostream>

int main() {
    using namespace std::chrono;

    year_month_day start{year{2025}, month{1}, day{1}};
    year_month_day end{year{2025}, month{10}, day{10}};

    auto diff = sys_days{end} - sys_days{start};
    std::cout << "Days between: " << diff.count() << " days\n";
}

输出:

在这里插入图片描述

四、混合使用:兼容旧接口

在实际工程中,常常需要兼容旧API(日志系统、数据库等)。

auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);
std::tm* tm = std::localtime(&t);

反向转换:

std::time_t t = std::time(nullptr);
auto tp = std::chrono::system_clock::from_time_t(t);

五、总结与最佳实践

需求推荐方案理由
获取系统时间std::chrono::system_clock::now()高精度、类型安全
计算时间间隔steady_clock不受系统调整影响
格式化输出std::format("{:%Y-%m-%d %H:%M:%S}", tp)简洁优雅
日期差值year_month_day + sys_days精准直观
与旧接口兼容<ctime> 转换平滑迁移

六、结语

time_tstd::chrono,C++ 的时间处理终于从“痛苦拼结构体”升级为“类型安全 + 可读 + 精准”的现代方案。

如果你还在用 std::tm 做日期计算,
不妨试试 std::chrono ——
它不仅让代码更优雅,也能避免那些年年踩的时间坑。


七、推荐阅读

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐