c++ - 如何使用 GCC 9 将 `std::filesystem::file_time_type` 转换为字符串
问题描述
我正在尝试将文件的修改时间格式化为字符串(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';
}
我尝试了decltype(file_time)::clock
and std::chrono::file_clock
,同时使用了 C++17 和 C++20,但它们都不起作用。
$ 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_clock
,to_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+
的持续时间和时间点的额外模板(2)和比率差异将在std::common_type
.
剩下的问题是,两个调用now()
不同时,由于调用之间的时间差,存在引入小的转换错误的轻微风险。还有一个关于 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';
}
推荐阅读
- reactjs - 如何在给定条件下用以前的数据填充文件输入(图像)值和名称?
- azure - 如果我想从 azure 函数查看 Kibana 日志,我应该在哪里安装 Filebeat?
- html - CSS,首选最小宽度的成语
- javascript - npm start 有 tailwind.js 弹出错误 800A0404 jScript 编译错误然后空白浏览器屏幕
- excel - 查看是否存在 excel 文件
- amazon-web-services - AWS 负载平衡未解析到 EC2 服务器
- google-classroom - Google Classroom API 说它已被禁用,但实际上并非如此
- caching - 无法绕过 Cloudflare 中我的 API 的动态状态缓存
- delphi - TIdHTTP 发布到 API 并将响应保存为 .pdf 文件
- python - 如何直接从 URL 读取大量 HDF5 文件目录到 Python?