std::filesystem::last_write_time 返回 file_time_type,需转为 system_clock::time_point 才能格式化:先 duration_cast 到秒级 time_t,再用 from_time_t 转换,最后通过 localtime_r/s 和 put_time 输出;注意跨平台编译选项与线程安全。

用 std::filesystem::last_write_time 获取时间点
在 C++17 及以上,std::filesystem::last_write_time 是标准、跨平台的方式获取文件最后修改时间。它返回的是 std::filesystem::file_time_type 类型的时间点,不是秒数或字符串,不能直接打印或格式化。
常见错误是试图对返回值做算术运算(比如加减秒)或直接传给 std::put_time —— 它和 std::chrono::system_clock::time_point 不兼容,必须先转换。
- 确保编译器支持 C++17(如 GCC 8+、Clang 7+、MSVC 2017 Update 3+)并启用
-std=c++17 - 链接时需加
-lstdc++fs(GCC,部分旧版本需要;Clang 同样可能需要;MSVC 内置支持) - 路径必须存在且可访问,否则抛出
std::filesystem::filesystem_error
把 file_time_type 转成 system_clock::time_point
关键难点在于时钟类型不兼容:file_time_type 通常基于系统底层文件时间(如 Windows FILETIME 或 Unix 纳秒级 st_mtim),而 std::chrono::system_clock::time_point 对应日历时间。C++20 引入了 clock_cast,但 C++17 没有标准转换函数,得手动处理。
可靠做法是:用 std::filesystem::file_time_type::clock::to_time_t(如果可用)或借助 std::chrono::duration_cast + 偏移量校准。不过最稳妥的 C++17 兼容方案是调用系统 API 做桥接——但更实用的是用 std::filesystem::last_write_time 配合 std::chrono::system_clock::from_time_t 中转:
立即学习“C++免费学习笔记(深入)”;
#include <filesystem>
#include <chrono>
#include <ctime>
#include <iostream>
<p>namespace fs = std::filesystem;</p><p>fs::file_time_type ftime = fs::last_write_time("test.txt");
auto sctp = fs::file_time_type::clock::to_time_t(ftime); // C++20 才保证存在
// 若编译失败,改用以下兼容写法(依赖实现但广泛可用):
auto dur = ftime.time_since_epoch();
auto secs = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
auto tp = std::chrono::system_clock::from_time_t(secs);
⚠️ 注意:file_time_type::clock::to_time_t 在 C++17 中不是强制要求实现,GCC/Clang 通常支持,MSVC 2019+ 支持;若不可用,上面的 duration_cast + from_time_t 是更保守的选择(精度损失到秒,但对“最后修改时间”显示足够)。
用 std::put_time 格式化输出
拿到 std::chrono::system_clock::time_point 后,就能用标准库格式化了。注意:必须先转成 std::time_t,再用 std::localtime 或 std::gmtime 转为 std::tm,最后用 std::put_time 输出。
-
std::localtime用本地时区,std::gmtime用 UTC;多数场景用localtime -
std::put_time的格式符和 C 的strftime一致,比如"%Y-%m-%d %H:%M:%S" - 不要忽略线程安全性:
std::localtime返回静态缓冲区指针,多线程下需用std::localtime_r(POSIX)或std::localtime_s(Windows)
auto tt = std::chrono::system_clock::to_time_t(tp);
std::tm tm_buf;
#ifdef _WIN32
localtime_s(&tm_buf, &tt);
#else
localtime_r(&tt, &tm_buf);
#endif
std::cout << std::put_time(&tm_buf, "%Y-%m-%d %H:%M:%S") << "\n";
完整可运行示例(C++17 兼容)
下面代码在 GCC/Clang/MSVC 上均能通过,不依赖 C++20 特性,输出形如 2024-05-22 14:36:01:
#include <filesystem>
#include <chrono>
#include <ctime>
#include <iostream>
#include <iomanip>
<p>int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <file>\n";
return 1;
}
try {
auto ftime = std::filesystem::last_write_time(argv[1]);
auto dur = ftime.time_since_epoch();
auto secs = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
auto tp = std::chrono::system_clock::from_time_t(secs);</p><pre class="brush:php;toolbar:false;"> std::time_t tt = std::chrono::system_clock::to_time_t(tp);
std::tm tm_buf{};ifdef _WIN32
std::localtime_s(&tm_buf, &tt);
else
std::localtime_r(&tt, &tm_buf);
endif
std::cout << std::put_time(&tm_buf, "%Y-%m-%d %H:%M:%S") << "\n";
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Error: " << e.what() << "\n";
return 1;
}}
真正容易被忽略的是时区隐含行为和精度取舍:last_write_time 在不同文件系统上精度不同(NTFS 是 100ns,ext4 通常是 1s),而我们截断到秒后转 system_clock,已经丢弃了亚秒信息——这不是 bug,而是权衡。如果需要毫秒级显示,就得绕过 time_t,用 std::chrono::high_resolution_clock 做映射,但那就不再是标准可移植方案了。



















