std::filesystem::last_write_time 返回 std::filesystem::file_time_type,其底层时钟不保证与 system_clock 可互转,需通过 file_time_type::clock::to_time_t 转 time_t 再转 system_clock::time_point。

std::filesystem::last_write_time 返回的是什么类型
std::filesystem::last_write_time 返回的是 std::filesystem::file_time_type,它不是 std::chrono::system_clock::time_point,也不是 std::chrono::steady_clock::time_point。这是最容易出错的第一步:直接拿它和 std::time_t 或 std::chrono::system_clock::from_time_t 强转会编译失败或行为未定义。
这个类型本质是实现定义的,但 C++20 要求它能通过 std::filesystem::file_time_type::clock 获取其底层时钟,且该时钟必须支持 to_time_t(C++20 起)——但注意:**它不保证与 system_clock 可互转**,尤其在 Windows 上,file_time_type 通常基于 std::chrono::utc_clock 或类似高精度文件时间(100ns 精度),而 system_clock 可能是基于 Unix epoch 的毫秒/微秒精度。
- 不要用
auto tp = std::chrono::system_clock::from_time_t(std::filesystem::last_write_time(p).time_since_epoch().count())—— 这是典型错误,单位、epoch、时区全错 - 正确做法是先转成
time_t,再进system_clock(需经中间转换) - Windows MSVC 下,
file_time_type默认对应FILETIME,Linux Clang/GCC 下通常映射到stat.st_mtim(timespec)
安全转成 time_t 再转 system_clock::time_point
C++20 提供了标准转换路径:std::filesystem::file_time_type → std::time_t → std::chrono::system_clock::time_point。关键中间步骤是调用 std::filesystem::file_time_type::clock::to_time_t(注意不是 system_clock::to_time_t)。
#include <filesystem> #include <chrono> #include <ctime><p>namespace fs = std::filesystem;</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a> <p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p> </div> <a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <p>fs::path p = "test.txt"; auto ftime = fs::last_write_time(p);</p> <p>// ✅ 正确:用 file_time_type 自带 clock 转 time_t std::time_t t = fs::file_time_type::clock::to_time_t(ftime);</p> <p>// ✅ 再转成 system_clock::time_point(忽略亚秒精度) auto tp = std::chrono::system_clock::from_time_t(t); </p></ctime></chrono></filesystem>
- 这一步丢弃了纳秒/100ns 级精度,但保证了时间值语义正确(UTC 秒数)
- 如果需要更高精度(比如保留毫秒),得走平台 API:Windows 用
FileTimeToSystemTime,Linux 用stat的st_mtim.tv_nsec - 若
ftime是file_time_type::min()(如文件不存在或权限不足),to_time_t可能返回 -1,需检查
跨平台处理无效时间或权限错误
std::filesystem::last_write_time 在遇到权限拒绝、符号链接悬空、路径不存在等情况时,**不会抛异常(默认不抛)**,而是返回 file_time_type::min()。很多开发者误以为它会 throw std::filesystem::filesystem_error,其实只有显式传入 std::filesystem::symlink_option::no_follow 或开启异常模式才可能抛。
- 默认行为是静默返回最小时间值:
ftime == fs::file_time_type::min()表示获取失败 - 建议始终检查:
if (ftime == fs::file_time_type::min()) { /* handle error */ } - 更健壮的做法是捕获异常并启用异常模式:
fs::last_write_time(p, ec),其中ec是std::error_code&,避免全局异常开销 - Windows 上对只读文件、网络驱动器、某些 NTFS 压缩文件也可能返回无效时间,不能只依赖
exists()判断
chrono duration 精度丢失的实际影响
file_time_type 在不同平台的精度差异很大:Windows 是 100 纳秒,Linux st_mtim 通常是纳秒,但 glibc 实现可能截断为微秒。当你用 to_time_t 转成秒级 time_t,再进 system_clock::from_time_t,得到的 time_point 只有秒精度 —— 原始毫秒/微秒信息彻底丢失。
- 如果业务需要比较两个文件修改时间谁更新(哪怕差 1ms),仅靠
to_time_t不够,得用原生file_time_type直接比较:ftime1 > ftime2是合法且精确的 - 想打印毫秒级时间字符串?别转
time_t,改用ftime.time_since_epoch()拿duration,再除以std::milli等 - 注意:
file_time_type::time_since_epoch()返回的是相对于其自身 epoch 的 duration,不是 Unix epoch,不能直接当毫秒戳用
实际项目里,最常被忽略的是“以为 last_write_time 总是有效”和“强行塞进 system_clock 导致时间偏移”。真要 UTC 时间戳做日志或网络传输,老实用 to_time_t;真要高精度比大小,就别转,直接用 file_time_type。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










