I'm using Howard Hinnant's time zone library.
https://howardhinnant.github.io/date/tz.html
My question: Is it possible to construct a date::local_time object from a std::chrono::time_point?
What I want to to:
// 'tp' exists and is some std::chrono::time_point object
auto locTime = date::local_time<std::chrono::milliseconds>(tp);
The constructor for this doesn't exist so a get a compilation error. How do I do this (in nice and clean C++17)?
Background:
My ultimate goal is to compare a std::filesystem::file_time_type
to a date::local_time<std::chrono::milliseconds>
.
I do
auto fileTimeTp = std::chrono::clock_cast<std::chrono::system_clock>(someDirectoryEntryObject.last_write_time());
which gives my my std::chrono::time_point for the file date, but that's where I'm stuck...
This is a two part answer ...
My question: Is it possible to construct a date::local_time object from a
std::chrono::time_point
?
I'm going to assume that std::chrono::time_point
refers to std::chrono::system_clock::time_point
(each clock has its own family of std::chrono::time_point
).
Yes, it is possible. Background: system_clock::time_point
is defined as Unix Time which is a close approximation to UTC. So to go from system_clock::time_point
(also know as sys_time
in the date library / C++20) to local_time
, you need to pair the sys_time
with a time_zone
. This could be your computer's current local time zone, or any other IANA time zone.
To get the computer's current local time zone:
auto tz = date::current_zone();
The type of tz
is a date::time_zone const*
. time_zone
has a member function called to_local
that will translate a sys_time
into a local_time
:
auto locTime = tz->to_local(system_clock::now());
The precision of locTime
will match whatever the precision of the input sys_time
is.
If you would like to use some other time zone, then you can use date::locate_zone
to get a date::time_zone const*
to that time zone.
auto locTime = date::locate_zone("America/New_York")->to_local(system_clock::now());
My ultimate goal is to compare a
std::filesystem::file_time_type
to adate::local_time<std::chrono::milliseconds>
.
Ah, this won't really involve local_time
at all. And unfortunately, file_clock
is not implemented in the time_zone library.
In C++20, this will be quite easy: Given a file_time
and a sys_time
you can convert either to the other using clock_cast
:
if (clock_cast<system_clock>(ftp) >= system_clock::now())
...
However in C++17 it is harder, and non-portable. The the time_zone library makes it easier, but not easy.
You first have to deduce the epoch of std::filesystem::file_time_type
on your platform. This will be different depending on which implementation of std::filesystem::file_time_type
you are using.
Existing epochs include:
* 1970-01-01 00:00:00 UTC
* 1601-01-01 00:00:00 UTC
* 2174-01-01 00:00:00 UTC
Then you subtract the sys_time
epoch (sys_days{1970_y/1/1}
) and the file_time
epoch (e.g. sys_days{1601_y/1/1}
), and add/subtract that epoch to convert from one measure to the other.
For example:
constexpr auto diff = sys_days{1970_y/1/1} - sys_days{1601_y/1/1};
file_time_type ftp = ...
system_clock::time_point tp{ftp.time_since_epoch() - diff};
That's unfortunately quite messy, and I'm looking forward to clock_cast
working with file_clock
in C++20.