date
date copied to clipboard
Exactly how is this different from the C++20 version?
I would like to keep using this library as a "fallback" for compilers that don't yet support C++20's new date facilities. I need to know exactly what's different between this version and the C++20 version (from an API standpoint) so that I can use preprocessor directives accordingly.
It would be useful to have a summary of differences documented somewhere.
Keep this issue open until I get it documented so that others can find this information more easily.
Differences between this library and C++20:
-
Everything is in the header
<chrono>
andnamespace std::chrono
, exceptformat
. -
date::format
is nowstd::format
which follows the syntax/design of thefmt
library. It has format strings that are slightly different than here. For example instead of:
std::string s = date::format("%F %T", tp);
one would say:
std::string s = std::format("{:%F %T}", tp);
-
make_zoned
does not exist in C++20. It is no longer needed because CTAD is used to deduce the template parameters ofzoned_time
. For example instead of:
auto zt = make_zoned(current_zone(), system_clock::now());
one writes:
zoned_time zt{current_zone(), system_clock::now()};
-
jan
,mon
, et al. are nowJanuary
,Monday
respectively. The std-style identifiers are also present in the date lib, so you can transition prior to C++20. -
time_of_day
is renamed tohh_mm_ss
. The namehh_mm_ss
also exists in the date lib, so you can transition prior to C++20. -
make_time
does not exist in C++20. It is no longer needed because CTAD is used to deduce the template parameters ofhh_mm_ss
. For example instead of:
auto tod = make_time(tp-sd);
one writes:
hh_mm_ss tod{tp-sd};
-
leap
was renamed toleap_seconds
. Both names are present in the date lib so that you can transition prior to C++20. -
link
was renamed totime_zone_link
. Both names are present in the date lib so that you can transition prior to C++20. -
The functions for downloading a new tzdb do not exist in C++20:
bool remote_download(const std::string& version);
bool remote_install(const std::string& version);
void set_install(const std::string& s);
Your vendor is responsible for keeping the time zone database up to date, and may or may not have the feature of being able to update the database while your application is running.
Excellent summary, thanks! Is this library's format
locale-indendent (that is, the overloads that don't take a locale
object)? Or put another way, do the format
overloads not taking a locale use the global locale or the classic locale?
global: http://eel.is/c++draft/time.format#2
Thanks, I incorrectly assumed the standard format
overloads not taking a locale
were locale-independent (which is different from the fmt library).
Other differences:
-
date::format
throwsstd::ios_base::failure
whereasstd::format
throwsstd::format_error
. - ~~No "exotic" clock types (such as
utc_clock
) in date library~~ (oops, they're intz.h
-- see comment below).
Actually utc_clock
, tai_clock
and gps_clock
are in tz.h. But file_clock
is not in this library.
I have unit tests that depend on running against deterministic versions of the TZ database. Currently I use the --tz_version
flag to specify the version (e.g. --tz_version 2020a
). It sounds like the removal of remote_download()
and related methods means that this flag will no longer be supported.
The next best thing would be the ability to freeze the TZ DB version at a known point, to get reproducible builds. Does the C++20 library specification guarantee that freezing the vendor-supplied library at a specific version will also freeze the TZ DB version? Or is the vendor-supplied library allowed to pickup whatever TZ DB version happens to be installed and upgraded on the host OS?
Finally, will the C++20 library provide the same TZ DB metadata info that is documented here (https://howardhinnant.github.io/date/tz.html#database)?
struct tzdb
{
string version;
vector<time_zone> zones;
vector<link> links;
vector<leap> leaps;
const time_zone* locate_zone(string_view tz_name) const;
const time_zone* current_zone() const;
};
The C++20 spec does not specify when or how often the vendor will upgrade the TZ DB. On some platforms (e.g. macOS) I expect one to have to install an OS patch (with subsequent reboot) to get an upgraded TZ DB. On Linux I expect it will be possible to upgrade the TZ DB while applications are running. I do not know if Linux asks for an admin ok prior to doing so (I would hope so). In any event, upgrading the installed TZ DB is likely to be an OS-driven event as opposed to a C++ tools driven event.
Yes, struct tzdb
is available in C++20: http://eel.is/c++draft/time.zone.db.tzdb
That being said, because of the way the IANA zic compiler processes links, it may be that links
is empty and all of those names are now distinct zones
. That also happens with this library when compiling with -DUSE_OS_TZDB=1
.
Also (and as noted above, but could be clearer), the names of some of these members has been slightly changed (e.g. leaps
-> leap_seconds
).
On Linux I expect it will be possible to upgrade the TZ DB while applications are running. I do not know if Linux asks for an admin ok prior to doing so (I would hope so).
FYI: On Debian/Ubuntu/Mint, the TZ DB is in the tzdata APT package which normally needs an admin ok when updating. Reboots are not necessary when updating a non-kernel package. It's possible to set-up auto updating on a regular basis (e.g. daily) where no user intervention is necessary.
Differences in the tzdb
fields:
C++20 | date |
---|---|
version |
version |
zones |
zones |
links (always present) |
links (absent when USE_OS_TZDB == 1 ) |
leaps |
leap_seconds (note different name) |
One difference I noticed recently is the <=>
operator is defined in the C++20 std::chrono::year_month_day
class, but not for date::year_month_day
. Not sure if this is by design, but it's something I did come across.
besides other differences in format string syntax (such as say leading "{:" and trailing "}") there's requirement that "A chrono-spec must start with a conversion specifier" and despite of "All ordinary characters are written to the output without modification" std::format won't let to use leading ordinary characters as date::format allowed