std::filesystem::last_write_time是C++17起跨平台获取文件最后修改时间的最直接方式,返回file_time_type需转换为system_clock::time_point再格式化,注意异常处理与纪元对齐。

用 std::filesystem::last_write_time 获取时间戳(C++17 起)
这是最直接、跨平台的方式,不依赖系统 API 或第三方库。前提是编译器支持 C++17 且启用 std::filesystem(GCC/Clang 需链接 -lstdc++fs,MSVC 默认支持)。
注意:std::filesystem::last_write_time 返回的是 std::filesystem::file_time_type,它和 std::chrono::system_clock 不直接兼容,不能直接传给 std::put_time。
- Linux/macOS/Windows 下行为一致,但底层时钟精度可能不同(如 Windows FAT32 只精确到 2 秒)
- 若文件不存在或无权限,会抛出
std::filesystem::filesystem_error,必须捕获 - 返回值不是 Unix 时间戳,是实现定义的时钟类型,需转换
把 file_time_type 转成 std::time_t 再格式化
核心难点在于时钟转换。标准做法是:先转为 std::chrono::system_clock::time_point,再转 std::time_t。但 C++20 才引入 clock_cast,C++17 需手动对齐纪元(epoch)。
可靠写法是用 std::filesystem::file_time_type::clock::to_time_t(如果可用),否则回退到基于纪元偏移的手动转换。实际中,MSVC 和较新 libstdc++ 支持 to_time_t,但 libc++(macOS 默认)不支持,所以更稳妥的是用 C++20 的 std::chrono::clock_cast —— 如果你不能用 C++20,就老实用 stat() 系统调用(见下一条)。
立即学习“C++免费学习笔记(深入)”;
- 不要用
auto t = last_write_time(p).time_since_epoch().count()直接当秒数用——单位不一定是秒,也可能是纳秒或 100ns - Linux 上
file_time_type通常基于system_clock,但标准不保证;Windows 上常基于steady_clock或自定义时钟 - 手动算 epoch 偏移容易出错,比如误把
file_time_type::epoch()当作 1970-01-01
备选方案:用 stat() + localtime_r/localtime_s
当 C++17 filesystem 不可用、或需要更高可控性(比如绕过权限检查失败时的异常)、或目标平台 libc 较旧(如某些嵌入式环境),直接调系统接口更稳。
POSIX(Linux/macOS)用 stat() 读 st_mtime;Windows 用 GetFileTime() 或 _stat64()。统一处理建议封装一层:
#ifdef _WIN32
struct _stat64 st;
if (_stat64(path.c_str(), &st) == 0) {
tm t;
localtime_s(&t, &st.st_mtime); // VS2013+
std::ostringstream oss;
oss << std::put_time(&t, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
#else
struct stat st;
if (stat(path.c_str(), &st) == 0) {
tm t;
localtime_r(&st.st_mtime, &t);
std::ostringstream oss;
oss << std::put_time(&t, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
#endif
-
localtime_r和localtime_s是线程安全版本,别用localtime -
_stat64比_stat支持大于 4GB 文件的修改时间(Windows) - 路径字符串需确保是本地编码(Windows 上宽字符路径要用
_wstat64)
时区与可读格式的关键细节
最后输出的“可读日期字符串”默认是本地时区。如果需要 UTC,用 gmtime_r/gmtime_s 替代 localtime_r/localtime_s;如果要 ISO 8601 格式,改用 "%Y-%m-%dT%H:%M:%SZ"(UTC)或带偏移(需额外获取 TZ info)。
-
std::put_time在某些旧 libc(如 musl)上可能不支持%z,慎用 - Windows 上
std::put_time对中文 locale 支持不稳定,建议固定用"C"locale:std::locale::global(std::locale("C")); - 毫秒级精度无法靠
std::put_time输出,st_mtim.tv_nsec(POSIX)或FILETIME(Windows)需单独提取并拼接
跨平台时间戳处理真正的麻烦不在获取,而在时钟类型转换和时区一致性。别假设 file_time_type 和 system_clock 可互转——查清你用的 STL 实现是否真正支持,比硬写转换逻辑更省事。


















