如何使用GCC 9将`std :: filesystem :: file_time_type`转换为字符串 [英] How to convert `std::filesystem::file_time_type` to a string using GCC 9

查看:282
本文介绍了如何使用GCC 9将`std :: filesystem :: file_time_type`转换为字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to format the modification time of a file as a string (UTC). The following code compiles with GCC 8, but not 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,但是它们都不起作用.

I tried both decltype(file_time)::clock and std::chrono::file_clock, using both C++17 and C++ 20, but neither of them worked.

$ 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一起使用吗?

The example on https://en.cppreference.com/w/cpp/filesystem/file_time_type mentions that it doesn't work on GCC 9, because C++20 will allow portable output, but I have no idea how to get it working. Shouldn't it work with GCC 9 if I just not use C++20?

如果可能的话,我希望使用带有GCC 9的C ++ 17解决方案.

I would prefer a C++17 solution with GCC 9, if possible.

推荐答案

由于system_clock具有to_time_t,最简单的方法是将其转换为它.这不是完美的(由于精度问题),但是大多数时候都足够好,而且我在MSVC上也使用了什么:

As system_clock has to_time_t, the easiest way is to convert to it. This is not perfect (due to precision issues), but most of the time good enough and what I'm using on MSVC as well:

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+,用于 ="duration "和时间点

Update: As I'm not yet able to comment, some clarification on why this works and what can be a problem: It works because the difference between two time points of the same clock is easy, and for the second part, there is an extra template operator+ for duration and time point of different sources (2) and ratio differences will be taken care of in std::common_type.

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

The remaining issue is, that the two calls to now() are not at the same time, there is a slight risk of introducing a small conversion error due to the time difference between that calls. There is another question about C++11 clock conversions that goes into much more detail on error probabilities and tricks to reduce the error, but if you don't need a round-trip conversion with comparing results, but just want to format a time stamp, this smaller solution should be good enough.

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

So to complete the answer to the original question:

#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';
}

这篇关于如何使用GCC 9将`std :: filesystem :: file_time_type`转换为字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆