c++oding="utf-8" ?>
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 系统上的安全路径:
// POSIX 示例:绕过 chrono,直接读 struct stat
#include <sys>
struct stat st;
if (stat("path/to/file", &st) == 0) {
time_t mtime = st.st_mtime; // 直接得到 Unix 时间戳
}
</sys>
若坚持用 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) <p>但要注意:</p> <ul> <li>这个转换只在 MSVC 的 <code>file_clock</code> 实现下有效;GCC/MinGW 默认不兼容</li> <li>若用 MinGW,<code>file_clock</code> 可能基于 <code>system_clock</code>,此时需先将 FILETIME 转为 Unix 时间戳再构造 <code>system_clock::time_point</code> </li> <li>调用 <code>GetFileTime</code> 前必须确保句柄有 <code>FILE_READ_ATTRIBUTES</code> 权限</li> </ul> <h3>std::chrono::file_clock::now() 不能用于测量耗时</h3> <p><code>file_clock::now()</code> 返回的是当前文件系统时间(即系统挂钟时间,但纪元不同),不是单调时钟。它的值可能因 NTP 同步、时区切换或管理员修改系统时间而跳跃,完全不适合做性能计时。</p> <p>如果你看到代码里写了 <code>auto start = file_clock::now(); ...; auto dur = file_clock::now() - start;</code> —— 这是严重误用。</p> <ul> <li>测耗时请无条件使用 <code>steady_clock</code> </li> <li>记录文件操作时间点才用 <code>file_clock</code> 或 <code>filesystem::last_write_time()</code> </li> <li> <code>file_clock</code> 的主要价值在于保持与文件系统 API 的类型一致,避免隐式转换错误,而不是提供“另一个计时器”</li> </ul> <p>文件时间转换最麻烦的地方不在公式,而在纪元差异和平台实现分歧。哪怕同一个函数名,在不同 STL 实现里底层可能是 system_clock、FILETIME 或 clock_gettime(CLOCK_REALTIME),别信文档,编译前先查你用的库源码。</p></uint64_t></chrono></windows.h>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










