std::chrono::file_clock 是 C++17 标准中唯一明确定义用于文件时间的时钟,其 time_point 类型与 std::filesystem::file_time_type 直接对应,可安全 round-trip 转换;其他时钟如 system_clock 或 steady_clock 无直接映射关系,强行转换不可移植且易出错。

std::chrono::file_clock 是唯一能直接转文件时间的时钟
Windows 和 POSIX 文件系统的时间戳(如 st_mtime)本质上是自某个纪元起的秒/纳秒数,但 C++17 引入的 std::chrono::file_clock 才是标准中明确定义用于文件时间的时钟。其他时钟(system_clock、steady_clock)与文件时间无直接映射关系,强行转换会出错或不可移植。
常见错误是用 system_clock::to_time_t() 去“猜”文件修改时间——这在 Linux 可能碰巧对,在 Windows(尤其启用了“UTC 文件时间”策略时)会差 8 小时甚至更多。
-
file_clock的纪元是实现定义的(通常是 Windows FILETIME 纪元:1601-01-01 UTC,或 Unix epoch,取决于平台),但标准保证它能 round-trip 转换std::filesystem::file_time_type - 所有
std::filesystemAPI 返回的时间类型都是file_time_type,其底层就是file_clock::time_point - 不要试图用
duration_cast在file_clock和system_clock之间硬转;要用clock_cast(C++20)或平台适配逻辑
从 std::filesystem::file_time_type 获取秒级时间戳(跨平台)
如果只是想把文件修改时间转成 Unix 时间戳(秒数),不能直接减去 system_clock::epoch,而应先转到 system_clock,再转 time_t。但注意:C++17 没有 clock_cast,需手动处理。
可行做法是借助 std::chrono::time_point_cast + 平台判断,或更稳妥地调用系统 API。以下是在支持 stat 的 POSIX 系统上的安全路径:
立即学习“C++免费学习笔记(深入)”;
// POSIX 示例:绕过 chrono,直接读 struct stat
#include <sys/stat.h>
struct stat st;
if (stat("path/to/file", &st) == 0) {
time_t mtime = st.st_mtime; // 直接得到 Unix 时间戳
}
若坚持用 filesystem API:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- C++17 中,
file_time_type到system_clock::time_point无标准转换方式;MSVC 和 libstdc++ 提供非标扩展(如_To_sys),但不可靠 - Clang/libc++ 会把
file_time_type当作system_clock处理(仅限 macOS/Linux),但这不是标准行为 - 真正可移植的做法:用
std::filesystem::last_write_time()得到file_time_type,然后只做相对比较(如“比某时间新?”),不转绝对时间戳
Windows 上 FILETIME → file_clock::time_point 的手动对齐
Windows 的 FILETIME 是 100 纳秒单位、纪元为 1601-01-01 UTC。而 file_clock 在 MSVC 中恰好使用相同纪元和精度,所以可以直接 reinterpret:
// Windows only,MSVC 或 clang-cl
#include <windows.h>
#include <chrono>
FILETIME ft;
GetFileTime(hFile, nullptr, nullptr, &ft);
uint64_t ft_int = (static_cast<uint64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
auto tp = std::chrono::file_clock::time_point{
std::chrono::nanoseconds{ft_int * 100}
};
但要注意:
- 这个转换只在 MSVC 的
file_clock实现下有效;GCC/MinGW 默认不兼容 - 若用 MinGW,
file_clock可能基于system_clock,此时需先将 FILETIME 转为 Unix 时间戳再构造system_clock::time_point - 调用
GetFileTime前必须确保句柄有FILE_READ_ATTRIBUTES权限
std::chrono::file_clock::now() 不能用于测量耗时
file_clock::now() 返回的是当前文件系统时间(即系统挂钟时间,但纪元不同),不是单调时钟。它的值可能因 NTP 同步、时区切换或管理员修改系统时间而跳跃,完全不适合做性能计时。
如果你看到代码里写了 auto start = file_clock::now(); ...; auto dur = file_clock::now() - start; —— 这是严重误用。
- 测耗时请无条件使用
steady_clock - 记录文件操作时间点才用
file_clock或filesystem::last_write_time() -
file_clock的主要价值在于保持与文件系统 API 的类型一致,避免隐式转换错误,而不是提供“另一个计时器”
文件时间转换最麻烦的地方不在公式,而在纪元差异和平台实现分歧。哪怕同一个函数名,在不同 STL 实现里底层可能是 system_clock、FILETIME 或 clock_gettime(CLOCK_REALTIME),别信文档,编译前先查你用的库源码。

















