最直接方案是用C++17的std::filesystem::last_write_time,需启用C++17标准并链接-lstdc++fs(GCC早期),路径须存在,返回file_time_type需经file_clock转为system_clock才能得到秒级时间戳。

用 std::filesystem::last_write_time 最直接,但得开 C++17
这是目前最标准、跨平台(Windows/macOS/Linux)的方案,不需要自己调系统 API。前提是编译器支持 C++17 且启用对应标准(如 g++ -std=c++17 或 MSVC /std:c++17)。
常见错误现象:std::filesystem 报 “identifier not found” 或链接失败 —— 大概率是没开 C++17,或者没连 -lstdc++fs(GCC 早期版本需要)。
- 路径必须存在且可访问,否则抛
std::filesystem::filesystem_error - 返回类型是
std::filesystem::file_time_type,不是秒数,不能直接 printf - 转成秒级时间戳要经过
std::chrono::system_clock::from_time_t中转,中间需用std::chrono::file_clock转换(C++20 起更简单,但 C++17 需多一步)
try {
auto ftime = std::filesystem::last_write_time("config.json");
auto sctp = ftime.time_since_epoch();
auto duration = std::chrono::duration_cast(sctp);
time_t tt = duration.count();
std::cout << ctime(&tt); // 输出可读时间
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Failed: " << e.what() << "\n";
}
Windows 下用 GetFileTime,别漏掉 LocalFileTimeToFileTime
如果项目卡在 C++11/14,或必须精确控制时区/精度(比如要毫秒级、不依赖 CRT),就得调 Win32 API。但这里有个经典坑:API 返回的是 UTC 时间,而 FILETIME 结构体本身不带时区信息,直接转 SYSTEMTIME 再用 mktime 会错。
- 必须用
FileTimeToLocalFileTime先转成本地时区的FILETIME,再转SYSTEMTIME -
GetFileTime的第三个参数是lpLastWriteTime,别传错位置(顺序是创建、最后访问、最后修改) - 手动生成
HANDLE时记得用GENERIC_READ权限,且FILE_FLAG_BACKUP_SEMANTICS对目录是必需的
Linux/macOS 用 stat 系统调用,注意 st_mtim 和 st_mtime 的区别
stat() 是最轻量、兼容性最好的方案,所有 POSIX 系统都支持。但结构体字段容易混淆:st_mtime 是秒级整数,st_mtim.tv_nsec 才是纳秒部分 —— 很多人只读前者,丢掉亚秒精度。
立即学习“C++免费学习笔记(深入)”;
- struct stat 的
st_mtim是struct timespec类型(C++11 起),包含tv_sec和tv_nsec - 用
st_mtime(旧式字段)只能拿到秒,且某些老 libc 可能不填满纳秒位 - 路径含中文或特殊字符时,确保传入的是正确编码的
char*(UTF-8 on Linux, UTF-8 or CFString on macOS)
struct stat sb;
if (stat("data.bin", &sb) == 0) {
auto sec = sb.st_mtim.tv_sec;
auto nsec = sb.st_mtim.tv_nsec;
std::cout << "Modified at " << sec << "." << nsec << "s\n";
}
跨平台封装要注意时区和精度对齐
如果你写一个通用函数,别指望各平台返回值能直接比较大小 —— Windows 的 FILETIME 是 100ns 单位,Linux 的 tv_nsec 是纳秒,C++17 的 file_time_type 是实现定义周期。最安全的做法是统一转成 std::chrono::system_clock::time_point(即 Unix 时间戳)再比。
- 不要用
time_t做中间类型存纳秒级时间,它只保证秒级 - macOS 上
stat的st_mtimespec字段名不同(是st_mtimespec而非st_mtim),需宏判断 - 硬链接场景下,所有链接共享同一
st_ino和修改时间,但std::filesystem::last_write_time不关心这个,行为一致
真正麻烦的从来不是“怎么取”,而是“取出来之后怎么算、怎么比、怎么显示”。时间单位、时区、精度这三样,漏一个就可能在凌晨两点看到文件“倒退”了两小时。











