Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将std::filesystem::file\u time\u类型转换为time\t?_C++_Chrono - Fatal编程技术网

C++ 如何将std::filesystem::file\u time\u类型转换为time\t?

C++ 如何将std::filesystem::file\u time\u类型转换为time\t?,c++,chrono,C++,Chrono,我使用MSVC2015为windows编写了一个解决方案,其中以下代码转换std::filesystem::last_write_time result time_t: time_t ftime = std::file_time_type::clock::to_time_t(fs::last_write_time("/Path/filename")) 它工作得很好。然后,当我尝试使用gcc 9.3(-std=C++2a)将解决方案移植到Linux时,我得到了以下错误: 错误:“to_time_

我使用MSVC2015为windows编写了一个解决方案,其中以下代码转换std::filesystem::last_write_time result time_t:

time_t ftime = std::file_time_type::clock::to_time_t(fs::last_write_time("/Path/filename"))
它工作得很好。然后,当我尝试使用gcc 9.3(-std=C++2a)将解决方案移植到Linux时,我得到了以下错误:

错误:“to_time_t”不是“std::chrono::time_point::clock”{aka'std::filesystem::_file_clock'}的成员

我搜索了一个解决方案,但我找到的是基于std::filesystem::last_write_time示例中包含的解决方案。解决方案如下所示:

auto ftime = fs::last_write_time(p);
std::time_t cftime = decltype(ftime)::clock::to_time_t(ftime);
不幸的是,这对我不起作用。事实上,这个例子有一条评论说它在MSVC(MSVC2015)或GCC 9中不起作用;C++20将允许便携式输出


现在,我被卡住了。。。如何使用gcc进行此转换?

在C++20之前?没有可移植的方法可以做到这一点。它在该版本的VisualStudio中工作,因为该版本的VS文件系统实现恰好使用了
system\u clock
作为文件系统时钟类型。这不是C++标准所要求的,但它是允许的。所以你的代码碰巧起作用了

在C++20之前,没有将两个时钟对齐的机制,因此可以将一个时钟的时间转换为另一个时钟的时间。因此,如果文件系统时钟不是系统时钟,那么你就不走运了。您必须使用实现如何实现其文件系统时钟的知识编写特定于实现的代码(基本上知道它使用的是什么纪元),以便可以手动将其转换为
系统时钟::时间点


C++20为
系统时钟
提供了一个在所有实现中使用的固定时间(UNIX时间),并要求
文件时钟
能够将其时间点转换为
系统时钟
时间点。

如前所述,在C++17中没有完美的方法。根据实际用例,使用可移植近似值可能足够好了。根据我对的回答,我想建议这里使用的helper函数:

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);
}
模板
标准:时间到时间(TP)
{
使用名称空间std::chrono;
auto-sctp=time\u point\u cast(tp-tp::clock::now()
+系统时钟::现在();
返回系统时钟::至时间(sctp);
}
请注意,它在每个时钟上都使用对
now()
的调用,因此它不是一个精确的、保证往返的解决方案,但它可能对您有用,直到库中的差距消除为止。它基于这样一个事实,即相同时钟的时间点之间的差异很容易,并且对于不同来源的
持续时间
时间点
有一个
操作符+

为了进一步降低相关错误的风险,我想指出一些统计分析是在哪里进行的
减少可能的错误的想法,但如果可以接受,我只使用上面的代码。

这不是对问题的直接回答,也可能不是一个可移植的解决方案, 但我在Visual Studio 2017中将std::filesystem::file_time_类型转换为std::chrono::system_clock::time_point(可以轻松转换为time_t)时遇到了类似的问题,这对我很有效,可能会帮助其他也在搜索中的人

using namespace std::chrono;

// a dummy file_time_type to work with
const auto ftp = std::filesystem::file_time_type::clock::now();

// get the ticks and subtract the file time epoch adjustment
const auto ticks = ftp.time_since_epoch().count() - __std_fs_file_time_epoch_adjustment;

// create a time_point from ticks
const auto tp = system_clock::time_point(system_clock::time_point::duration(ticks));

// finaly convert to time_t
std::time_t tt = system_clock::time_point::clock::to_time_t(tp);

经过一番挖掘,我成功地改写了他们给出的例子,似乎奏效了;钥匙正在转换为
系统时钟
,然后转换为
时间

#include <iostream>
#include <chrono>
#include <iomanip>
#include <fstream>
#include <filesystem>
namespace fs = std::filesystem;
using namespace std::chrono_literals;
int main()
{
  fs::path p = fs::current_path() / "example.bin";
  std::ofstream(p.c_str()).put('a'); // create file
  auto ftime = fs::last_write_time(p);
  auto cftime = std::chrono::system_clock::to_time_t(std::chrono::file_clock::to_sys(ftime));

  std::cout << "File write time is " << std::asctime(std::localtime(&cftime)) << '\n';

  fs::last_write_time(p, ftime + 1h); // move file write time 1 hour to the future
  ftime = fs::last_write_time(p);     // read back from the filesystem

  cftime = std::chrono::system_clock::to_time_t(std::chrono::file_clock::to_sys(ftime));
  std::cout << "File write time is " << std::asctime(std::localtime(&cftime)) << '\n';
  fs::remove(p);
}
#包括
#包括
#包括
#包括
#包括
名称空间fs=std::filesystem;
使用名称空间std::chrono_文本;
int main()
{
fs::path p=fs::current_path()/“example.bin”;
std::ofstream(p.c_str()).put('a');//创建文件
自动ftime=fs::上次写入时间(p);
auto cftime=std::chrono::system_clock::to_time_t(std::chrono::file_clock::to_sys(ftime));

std::cout另一个非直接解决方案:如果您碰巧使用boost

    inline std::string filestamp(const std::string& path) {
        std::time_t t = boost::filesystem::last_write_time(path);
        return std::asctime(std::localtime(&t));
    }

这在C++17中适用。使用FileTimeToSystemTime以人类可读的格式返回文件时间。然后使用mktime转换为时间

auto filetime = entry.last_write_time();
SYSTEMTIME  stSystemTime;
if (FileTimeToSystemTime((const FILETIME*)&filetime, &stSystemTime))
{
printf("Year = %d,  Month = %d,  Day = %d,  Hour = %d,  Minute = %d\n", stSystemTime.wYear, stSystemTime.wMonth, stSystemTime.wDay, stSystemTime.wHour, stSystemTime.wMinute);
}

我可以看到这个固定纪元没有在gcc 9.3上实现(我用-std=C++2a进行了尝试)。也许它是在gcc 10上实现的?@Thearquite我认为变化是,并且根据上次页面更新时只有
libc++
clang
)部分支持它。