Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert std::filesystem::file_time_type to time_t?

Tags:

c++

chrono

I wrote a solution for windows using MSVC2015 where the follow code converts the 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"))

It works well. Then when I tried to port the solution to Linux using gcc 9.3 (-std=C++2a) I've got the follow error:

Error: 'to_time_t' is not member of 'std::chrono::time_point::clock' {aka 'std::filesystem::__file_clock'}

I searched for a solution, but what I found is based on solution included on example of std::filesystem::last_write_time at cplusplus.com. The solution is shown bellow:

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

Unfortunately it doesn't work to me. Actually, the example has a comment that say it won't work at MSVC(worked at MSVC2015) or GCC 9; C++20 will allow portable output.

Now, I'm stuck... How can I make this conversion using gcc?

like image 790
TheArchitect Avatar asked Apr 04 '20 15:04

TheArchitect


People also ask

How do I convert a Unix time_t file to a Win32 format?

The following function converts a filetime in the UNIX time_t format to a Win32 FILETIME format. Note that time_t is a 32-bit value and FILETIME is a 64-bit structure, so the Win32 function, Int32x32To64 () is used in the following function:

How are file times maintained in Unix?

Under UNIX platforms, file times are maintained in the form of a ANSI C runtime arithmetic type named 'time_t', which represents seconds since midnight January 1, 1970 UTC (coordinated universal time).

How are file times maintained under Win32?

Under Win32 platforms, file times are maintained primarily in the form of a 64-bit FILETIME structure, which represents the number of 100-nanosecond intervals since January 1, 1601 UTC (coordinate universal time). This article shows how to convert UNIX time to other Win32 time formats.

How to convert time to time_t in C++17?

This worked for me in C++17. Use FileTimeToSystemTime to return the file time in a human-readable format. From there you use using mktime to convert to time_t.


Video Answer


1 Answers

As already said, there is no perfect way to do that in C++17. Depending on the actual use-case it might be good enough to use a portable approximation. Based on my answer to "How to convert std::filesystem::file_time_type to a string using GCC 9", I want to suggest the helper function used there:

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);
}

Be aware, that it uses a call to now() on each clock, so it is not an exact, round-trip-guaranteed solution, but it might be usable for you, until the gap in the library is closed. It is based on the fact that difference between time points of the same clock is easy and there is an operator+ for duration and time_point of different sources.

For ways to lower the risk of a relevant error even more, I want to point to the conversion between C++11 clocks where some statistical analysis was made with ideas to mitigate possible errors, but when acceptable, I just use the code above.

like image 58
Gulrak Avatar answered Oct 24 '22 06:10

Gulrak