将 std::filesystem::file_time_type 转换为 epoch 纳秒?

Convert std::filesystem::file_time_type to epoch nanoseconds?

提问人:Markstar 提问时间:10/25/2023 最后编辑:genpfaultMarkstar 更新时间:10/26/2023 访问量:143

问:

我正在尝试使用 C++20 读取文件的上次修改日期/时间并将其转换为纳秒(我想微秒也足够了)。

以下是我的尝试:

int main() {
    std::filesystem::path myFile("D:\\myfile.png");
    if (std::filesystem::exists(myFile)) {
      std::filesystem::file_time_type ftime = std::filesystem::last_write_time(myFile);
      auto epoch = ftime.time_since_epoch();
      auto nano = std::chrono::duration_cast<std::chrono::nanoseconds>(epoch).count();
      const auto systemTime = std::chrono::clock_cast<std::chrono::system_clock>(ftime);
      const auto time = std::chrono::system_clock::to_time_t(systemTime);
      std::cout << std::format("ftime: {}\nepoch: {}\nnano: {}\nsystemtime: {}\ntime: {}\n", ftime, epoch, nano, systemTime, time);
    }
    else {
      std::cerr << "File does not exist." << std::endl;
    }
    return 0;
  }

输出为:

ftime: 2021-11-15 08:54:38.5861611
epoch: 132814400785861611[1/10000000]s
nano: -5165303995123390516
systemtime: 2021-11-15 08:54:38.5861611
time: 1636966478
  • ftime是文件显示的正确时间
  • epoch但是,并且是无效日期。nano
  • systemTime似乎已经把它转换回来了?但是在调试器中,似乎有正确的值(“16369664785861611”)systemTime
  • time是最接近的,但不够精确。

可悲的是,我无法弄清楚如何使用 的转换以及正确的语法是什么,所以我希望能得到一些帮助,以找出我错了哪里。std::chrono

C 转换 C++-Chrono

评论

0赞 pptaszni 10/25/2023
尝试用于您的 .另外,在 godbolt 中快速尝试并且无法重现。std::uint_64nano
0赞 Miles Budnek 10/26/2023
请记住,这是相对于时钟纪元的,该纪元通常是 UNIX 纪元(但不一定是 1970 年 1 月 1 日午夜)。具体而言,Windows 文件时间纪元不同(1601 年 1 月 1 日午夜)。实现知道这一点,但一个简单的方法看起来是错误的,因为你要把它与错误的纪元进行比较。time_since_epochclock_casttime_since_epoch
0赞 Markstar 10/26/2023
@pptaszni 感谢您的回复!该代码有效,但并不是我真正要问的。更改为没有改变任何东西。auto nanostd::uint64_t
0赞 Markstar 10/26/2023
@MilesBudnek嗯,可能就是这样,因为我在 Windows 上。不过,我仍然无法让它工作。
0赞 Miles Budnek 10/26/2023
你试过吗?我手边没有 Windows 盒子,但我希望它会给你你想要的。duation_cast<nanoseconds>(systemTime.time_since_epoch()).count()

答:

3赞 Miles Budnek 10/26/2023 #1

Windows 文件时间使用的纪元不是 UNIX 纪元。Windows 文件时间使用 1601 年 1 月 1 日午夜 UTC 纪元,而不是 1970 年 1 月 1 日午夜 UTC 的 UNIX 纪元。

这意味着 Windows 上的纪元不是 UNIX 纪元,因此您的调用返回的是自 Windows 文件纪元以来的时间,而不是 UNIX 纪元。std::filesystem::file_time_typetime_since_epoch

当你这样做时,你的时间会调整到 UNIX 时代,因为这就是用处。这意味着获得自 你的 纪元以来的纳秒数应该会给你你想要的答案:clock_caststd::chrono::system_clocksystemTimetime_point

auto timeSinceUnixEpoch = systemTime.time_since_epoch();
uint64_t nanosSinceUnixEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(timeSinceUnixEpoch).count();

请记住,您将无法获得完整的纳秒精度,因为 NTFS 以 100 纳秒的精度存储时间。

评论

0赞 Markstar 10/26/2023
谢谢,这行得通!所以我是否正确理解了这一点:为了获得正确的时间,我必须将文件()的时间转换为。然后将其转换为自正确日期开始以来的时间(Linux 为 1601 年,Windows 为 1970 年)。最后将其转换为微秒。这是对的吗?另外,为什么我需要在最后一步进行投射?不应该已经产生纳秒了吗?file_time_typesystem_clockcountcount()
1赞 Miles Budnek 10/26/2023
ftime是 上的一个,它测量自 1601 年以来的时间。虽然没有单位;这只是一个时间点(从逻辑上讲)。然后你必须把它带到 ,它测量自 1970 年以来的时间。你仍然只有一个时间点,但它基于不同的时钟。time_pointfile_clocktime_pointclock_castsystem_clock
1赞 Miles Budnek 10/26/2023
time_since_epoch然后给出时钟的纪元(1970 年,在 的情况下)和 ur 之间的时间,但没有指定该持续时间的单位表示。您必须使用它才能获得正确的单位。不过,它仍然是一个,您必须调用它才能将其转换为简单的整型。durationsystem_clocktime_pointduration_castdurationcount
0赞 Markstar 10/27/2023
感谢您抽出宝贵时间对此进行详细解释!