web-dev-qa-db-ja.com

time_tとstd :: filesystem :: file_time_typeを比較する方法

一部のコードを_boost::filesystem_から_std::filesystem_に変換しています。以前に使用したコード boost::filesystem::last_write_time() これは_time_t_を返すため、すでに保持している_time_t_オブジェクトと直接比較するのは簡単でした。ちなみに、私が持っているこの_time_t_はずっと前に保持されていたファイルの内容から読み取られたので、この「 unixエポック」タイプ。

_std::filesystem::last_write_time__std::filesystem::file_time_type_ を返します。 _file_time_type_を_time_t_に変換する、または2つのオブジェクトを移植可能に比較する移植可能な方法はありますか?

_#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?
}
_

[〜#〜] edit [〜#〜]cppreference.comの_last_write_time_のサンプルコードに注意してください は、クロックが_std::chrono::system_clock_関数を実装する _to_time_t_ であると想定していることを示します。この仮定は常に正しいとは限らず、私のプラットフォーム(VS2017)には当てはまりません。

9
PeteUK

リンクしたまさにその記事は、これを行う方法を示しています:to_time_tの対応するclockfile_time_typeメンバーを介して。

自分のリンクからコピーして貼り付けます。

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や友人を通じて適切に時間をキャストする必要があります。

4
SergeyA

Fwiw、C++ 20がここに来ると、ポータブルソリューションは次のようになります。

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

これにより、time_tfile_timeに変換されますが、その逆はありません。このアプローチの利点は、通常、file_timeの精度がtime_tよりも高いことです。 file_timetime_tに変換すると、変換中にその精度が失われるため、比較が不正確になるリスクがあります。

5
Howard Hinnant

同じ問題に直面し、VisualStudio専用のコードを使用して解決しました。

VSの場合、_wstati64関数(WindowsはUtf16でUnicodeパスをエンコードするため、ワイド文字の場合はw)とwstringpath変換を使用します。クラス。

すべてがこの関数に集められます:

#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
}
4
S.Clem