c++ - 如何使用 GCC 9 将 `std::filesystem::file_time_type` 转换为字符串

标签 c++ std-filesystem gcc9

我正在尝试将文件的修改时间格式化为字符串(UTC)。以下代码可以使用 GCC 8 进行编译,但不能使用 GCC 9 进行编译。

#include <chrono>
#include <filesystem>
#include <iomanip>
#include <iostream>
#include <sstream>

namespace fs = std::filesystem;

int main() {
    fs::file_time_type file_time = fs::last_write_time(__FILE__);
    std::time_t tt = decltype(file_time)::clock::to_time_t(file_time);
    std::tm *gmt = std::gmtime(&tt);
    std::stringstream buffer;
    buffer << std::put_time(gmt, "%A, %d %B %Y %H:%M");
    std::string formattedFileTime = buffer.str();
    std::cout << formattedFileTime << '\n';
}

我使用 C++17 和 C++ 20 尝试了 decltype(file_time)::clockstd::chrono::file_clock,但两者都没有工作了。

$ g++-9 -std=c++2a -Wall -Wextra -lstdc++fs file_time_type.cpp

file_time_type.cpp: In function ‘int main()’:
file_time_type.cpp:12:50: error: ‘to_time_t’ is not a member of ‘std::chrono::time_point<std::filesystem::__file_clock>::clock’ {aka ‘std::filesystem::__file_clock’}
   12 |     std::time_t tt = decltype(file_time)::clock::to_time_t(file_time);
      |                                                  ^~~~~~~~~

https://en.cppreference.com/w/cpp/filesystem/file_time_type 上的示例提到它在 GCC 9 上不起作用,因为 C++20 将允许可移植输出,但我不知道如何让它工作。如果我不使用 C++20,它不应该在 GCC 9 上工作吗?

如果可能的话,我更喜欢使用 GCC 9 的 C++17 解决方案。

最佳答案

由于system_clockto_time_t,最简单的方法就是转换成它。这并不完美(由于精度问题),但大多数时候都足够好,我也在 MSVC 上使用:

template <typename TP>
std::time_t to_time_t(TP tp)
{
    using namespace std::chrono;
    auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now()
              + system_clock::now());
    return system_clock::to_time_t(sctp);
}

更新:由于我还无法发表评论,请澄清一下为什么会出现这种情况以及可能出现的问题:它之所以有效,是因为同一时钟的两个时间点之间的差异很容易,对于第二部分,有一个额外的模板 operator+ 用于 different sources (2)持续时间时间点比率差异将在 std::common_type 中处理。

剩下的问题是,对 now() 的两次调用不是同时进行的,由于调用之间的时间差,存在引入小转换错误的轻微风险。有another question关于 C++11 时钟转换,其中更详细地介绍了错误概率和减少错误的技巧,但如果您不需要比较结果的往返转换,而只是想格式化时间戳,则此较小解决方案应该足够好。

因此,要完成原始问题的答案:

#include <chrono>
#include <filesystem>
#include <iomanip>
#include <iostream>
#include <sstream>

namespace fs = std::filesystem;

template <typename TP>
std::time_t to_time_t(TP tp)
{
    using namespace std::chrono;
    auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now()
              + system_clock::now());
    return system_clock::to_time_t(sctp);
}

int main() {
    fs::file_time_type file_time = fs::last_write_time(__FILE__);
    std::time_t tt = to_time_t(file_time);
    std::tm *gmt = std::gmtime(&tt);
    std::stringstream buffer;
    buffer << std::put_time(gmt, "%A, %d %B %Y %H:%M");
    std::string formattedFileTime = buffer.str();
    std::cout << formattedFileTime << '\n';
}

关于c++ - 如何使用 GCC 9 将 `std::filesystem::file_time_type` 转换为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56788745/

相关文章:

c++ - Windows API编程为什么需要RegisterClass?

c++ - '<一些系统头> : error: ‘<insert function here>’ is not a member of ‘std’ ' after moving source file

c++ - 编译器错误 : is private within this context only on gcc9 with c++17

c - 获取左移负数的警告

c++ - 从旧 API 到新 API YAMLcpp 的 GetNextDocument() 转换

c++ - 虚函数,为什么这里调用的是基类函数呢?

c++ - 在对std::filesystem::canonical()或std::filesystem::weakly_canonical()的调用上,lexically_normal()是否冗余?

c++ - 标准 C++ 中的非空相对当前路径?

c++ - 从std::filesystem::path C获取绝对路径

C++ 异步 OutputDebugString