【问题标题】:How to compare time_t and std::filesystem::file_time_type如何比较 time_t 和 std::filesystem::file_time_type
【发布时间】:2018-12-18 18:29:13
【问题描述】:

我正在将一些代码从boost::filesystem 转换为std::filesystem。以前的代码使用了boost::filesystem::last_write_time(),它返回一个time_t,所以直接比较我已经持有的time_t对象是微不足道的。顺便说一句,我持有的这个time_t从很久以前保存的文件内容中读取的,所以我坚持使用这种“自unix epoch以来的时间”类型。

std::filesystem::last_write_time 返回一个std::filesystem::file_time_type。是否有一种可移植的方式将 file_time_type 转换为 time_t,或者以其他方式可移植地比较这两个对象?

#include <ctime>
#include <filesystem>

std::time_t GetATimeInSecondsSince1970Epoch()
{
    return 1207609200;  // Some time in April 2008 (just an example!)
}

int main()
{
    const std::time_t time = GetATimeInSecondsSince1970Epoch();
    const auto lastWriteTime = std::filesystem::last_write_time("c:\\file.txt");

    // How to portably compare time and lastWriteTime?
}

编辑:请注意sample code at cppreference.com for last_write_time 声明它假设时钟是实现to_time_t 函数的std::chrono::system_clock。这个假设并不总是正确的,并且不在我的平台上(VS2017)。

【问题讨论】:

  • The documentation 引用to_time_t,这可能会做你想做的事。
  • C++ 库没有指定将一个时钟上的时间点转换为不同时钟上的等效时间点的方法,而且在许多情况下根本不可能进行转换。我看到的唯一选择是将所有查看文件时间戳的代码转换为使用 last_write_time 的时钟。
  • @tadman 已编辑问题以澄清为什么我无法访问 to_time_t()
  • @SamVarshavchik 我尽可能从文件系统的时钟中获取时间点,例如std::filesystem::file_time_type::clock::now(),但我有这些讨厌的 Unix 纪元时间戳很久以前就存在了。我现在看到这是一个糟糕的决定。猜我需要使用stat()
  • @PeteUK 因为你不在 Unix 文件系统上,所以使用 Unix 时间戳可能不是最好的设计选择。

标签: c++ chrono boost-filesystem


【解决方案1】:

Fwiw,当 C++20 出现时,可移植的解决方案将是:

clock_cast<file_clock>(system_clock::from_time_t(time)) < lastWriteTime

这会将time_t 转换为file_time,反之亦然。这种方法的优点是file_time 通常比time_t 具有更高的精度。将file_time 转换为time_t 会在转换过程中失去精确度,从而可能导致比较不准确。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,我使用 Visual Studio 的专用代码解决了它。

    对于 VS,我使用 _wstati64 函数(w 用于宽字符,因为 Windows 在 Utf16 中编码 Unicode 路径)和 wstring 转换 path 类。

    整个事情都集中在这个函数中:

    #if defined ( _WIN32 )
    #include <sys/stat.h>
    #endif
    
    std::time_t GetFileWriteTime ( const std::filesystem::path& filename )
    {
        #if defined ( _WIN32 )
        {
            struct _stat64 fileInfo;
            if ( _wstati64 ( filename.wstring ().c_str (), &fileInfo ) != 0 )
            {
                throw std::runtime_error ( "Failed to get last write time." );
            }
            return fileInfo.st_mtime;
        }
        #else
        {
            auto fsTime = std::filesystem::last_write_time ( filename );
            return decltype ( fsTime )::clock::to_time_t ( fsTime );
        }
        #endif
    }
    

    【讨论】:

      【解决方案3】:

      您链接的文章显示了如何做到这一点:通过file_time_type 的相应clockto_time_t 成员。

      从您自己的链接复制粘贴:

      auto ftime = fs::last_write_time(p);
      std::time_t cftime = decltype(ftime)::clock::to_time_t(ftime); 
      

      如果您的平台没有为您提供system_clock 作为file_time_type 的时钟,那么就没有可移植的解决方案(至少在file_time_type 时钟标准化时的C++20 之前)。在此之前,您必须弄清楚它实际上是什么时钟,然后通过duration_cast 和朋友适当地投射时间。

      【讨论】:

      • 链接的文章仅显示了一个假设时钟类型为 system_clock 的示例。无法做出该假设,并且在 VS2017 上它不是 system_clock,因此 to_time_t 不可用。我将编辑我的问题以提及这一点。
      • @PeteUK 我添加了一些措辞(说明在这种情况下没有便携式解决方案)。
      • 欣赏它。感谢您考虑我的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 2020-11-04
      • 1970-01-01
      相关资源
      最近更新 更多