C++ 获取当前时间

在 C++ 中,如果我们想获取电脑当前的真实日期和时间(即现在是哪一年几月几日、几点几分几秒),最常用的做法是使用 <chrono> 头文件中的 system_clock 配合 <ctime> 中的时间转换函数。

拿到系统时间点之后,我们既可以将其格式化成 "2026-10-24 15:30:00" 这样的常见日期字符串,也可以单独提取出里面的年月日、星期和时分秒。

获取当前时间并格式化输出

调用 std::chrono::system_clock::now() 就能拿到当前的系统时间点。不过要注意,它返回的是一个 time_point 时间点对象,默认不能直接当成日期字符串打印出来。

由于 C++11 引入的 <chrono> 主要负责高精度计时,本身没有提供直接拆解 “年月日” 的函数,因此我们可以结合 <ctime> 与 <iomanip> 头文件,按固定步骤完成转换与格式化输出。

语法:

std::time_t t = std::chrono::system_clock::to_time_t(时间点);
std::tm* p = std::localtime(&t);
std::cout << std::put_time(p, "格式字符串");

说明:

上面这 3 行代码依次完成了 3 步转换:

  • 转换为 time_t 类型:调用 system_clock::to_time_t(),将系统时间点转换为 C 风格的时间值 std::time_t。
  • 拆解为本地日历时间:调用 <ctime> 中的 std::localtime(&t)(注意变量前要加取地址符 &),根据电脑当前所在的时区拆解出包含年、月、日、时、分、秒的结构体指针 p。
  • 按格式输出:调用 <iomanip> 中的 std::put_time(),按照指定的格式字符串打印日期时间。这套写法在主流编译器上兼容性最好,平时直接当成固定组合使用即可。

示例 1:按标准格式输出当前时间

#include <chrono>
#include <ctime>      // 提供 std::localtime()
#include <iomanip>    // 提供 std::put_time()
#include <iostream>

int main() {
    // 获取当前系统时间点
    auto now = std::chrono::system_clock::now();

    // 转为本地日历时间结构体
    std::time_t t = std::chrono::system_clock::to_time_t(now);
    std::tm* p = std::localtime(&t);

    std::cout << std::put_time(p, "%Y-%m-%d %H:%M:%S") << '\n';
    return 0;
}

运行结果如下。

2026-10-24 15:30:00

分析:

在这个例子中,我们先按固定步骤拿到了本地时间指针 p,再通过 std::put_time() 将其按 "%Y-%m-%d %H:%M:%S" 格式打印出来。由于程序读取的是运行那一刻的真实电脑时间,当你在自己电脑上运行时,看到的就是当前的最新日期和时间。

在格式字符串 "%Y-%m-%d %H:%M:%S" 中,用到的 6 个格式符直接对应英文单词首字母(注意严格区分大小写),具体含义如下表所示。

常用日期时间格式符
格式符 英文来源 含义说明 输出示例
%Y Year(年) 4 位数的完整年份 2026
%m month(月) 2 位数的月份,不足 2 位自动补 0(01~12) 10
%d day(日) 2 位数的日期,不足 2 位自动补 0(01~31) 24
%H Hour(时) 24 小时制的小时(00~23) 15
%M Minute(分) 2 位数的分钟(00~59) 30
%S Second(秒) 2 位数的秒数(00~59) 00

提示 在咱们配置好的 VSCode(GCC)或在线编译器下,上面的代码可以直接编译运行。如果小伙伴们在 Windows 上使用 Visual Studio(MSVC)编译,遇到 localtime 相关的 C4996 安全报错,可以在代码最顶部(所有 #include 之前)加上一行 #define _CRT_SECURE_NO_WARNINGS 来解决。

自定义常见的日期时间格式

掌握了上面的 6 个基本格式符后,我们只需要调整格式字符串里的连接符号或组合顺序,就能把同一个时间指针 p 格式化成各种常见的显示样式。请看下面例子。

示例 2:输出不同格式的日期时间

#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>

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

    std::cout << std::put_time(p, "%Y-%m-%d") << '\n';
    std::cout << std::put_time(p, "%Y/%m/%d") << '\n';
    std::cout << std::put_time(p, "%H:%M:%S") << '\n';
    std::cout << std::put_time(p, "%Y%m%d_%H%M%S") << '\n';
    return 0;
}

运行结果如下。

2026-10-24
2026/10/24
15:30:00
20261024_153000

分析:

在上面代码中,我们只调用了一次 system_clock::now() 和 std::localtime(),接着就能通过 std::put_time() 输出横杠日期、斜杠日期、纯时间或常用于日志文件命名的紧凑格式(如 20261024_153000)。遇到个位数的月份或时分秒时(比如早上 8 点 5 分),格式符还会自动在左侧补 0 显示为 08:05。

单独提取年月日与时分秒

有些时候,我们不仅想把时间打印成字符串,还需要单独拿出 “今年是哪一年”、“现在是几月”、“今天是星期几” 的整数值来做条件判断,比如判断今天是不是周末。

前面调用的 std::localtime(&t) 返回的是一个指向 std::tm 类型的结构体指针,我们可以通过箭头运算符 -> 访问它内部的整型成员。常用的成员如下表所示。

std::tm 常用成员
成员名称 表示含义 取值范围与换算规则
tm_year 年份偏移量 自 1900 年算起的年数,实际年份为 tm_year + 1900
tm_mon 月份下标 范围是 0~11(0 代表 1 月),实际月份为 tm_mon + 1
tm_mday 当月几号 范围是 1~31,直接表示当月几号,无需加 1
tm_hour 小时 范围是 0~23(24 小时制)
tm_min 分钟 范围是 0~59
tm_sec 秒数 范围通常是 0~59
tm_wday 星期几 范围是 0~6(0 代表星期日,1~6 代表星期一至星期六)

下面我们通过一个示例,看看怎样单独提取这些整数值,并配合字符串数组将 tm_wday 转换为中文星期几。

示例 3:提取年月日与时分秒

#include <chrono>
#include <ctime>
#include <iostream>
#include <string>

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

    int year = p->tm_year + 1900;    // 年份需加 1900
    int month = p->tm_mon + 1;       // 月份需加 1
    int day = p->tm_mday;
    int hour = p->tm_hour;
    int minute = p->tm_min;
    int second = p->tm_sec;

    // 0 对应星期日,依此类推
    std::string weeks[7] = {
        "星期日", "星期一", "星期二", "星期三",
        "星期四", "星期五", "星期六"
    };
    std::string weekday = weeks[p->tm_wday];

    std::cout << "日期:" << year << " 年 " << month << " 月 ";
    std::cout << day << " 日 " << weekday << '\n';
    std::cout << "时间:" << hour << " 时 " << minute << " 分 ";
    std::cout << second << " 秒\n";
    return 0;
}

运行结果如下。

日期:2026 年 10 月 24 日 星期六
时间:15 时 30 分 0 秒

分析:

提取年月日时,最关键的两处换算是 p->tm_year + 1900 和 p->tm_mon + 1。这是因为 std::tm 沿用了早期 C 语言的设计:tm_year 记录的是距离 1900 年过去了多少年,比如 2026 年对应的 tm_year 是 126。

而 tm_mon 记录的是从 0 开始的月份下标(0~11),方便直接作为数组下标查询 12 个英文月份名,只有表示几号的 tm_mday 直接就是 1~31。此外,tm_wday 使用 0~6 表示星期几,其中 0 代表 “星期日”,因此我们把 "星期日" 放在 weeks 数组的第 1 项。

平时单独读取年月日时,小伙伴们只要记住一句口诀:“年加 1900,月加 1,几号直接取”。下面这种忘记换算直接赋值的写法就是错误的,会把 2026 年 10 月算成 126 年 9 月。

// 错误方式
int wrongYear = p->tm_year;    // 得到 126,而非 2026
int wrongMonth = p->tm_mon;    // 10 月会得到 9

C++20 直接格式化时间

从 C++20 开始,<chrono> 进一步补齐了日历与时区功能。在完整支持 C++20 标准的新版编译器中引入 <format> 头文件后,我们可以直接调用 std::format(如 std::format("{:%Y-%m-%d}", now))生成日期字符串,省去 std::localtime() 的转换步骤。

不过部分旧版编译器或在线评测环境对 C++20 时区库的支持还不完整。在实际开发中,前面学习的 to_time_t() 配合 std::localtime() 依然是兼容性最好的通用写法。

上一篇:

下一篇:

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号