Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exactly how is this different from the C++20 version? #565

Open
ecorm opened this issue Apr 3, 2020 · 13 comments
Open

Exactly how is this different from the C++20 version? #565

ecorm opened this issue Apr 3, 2020 · 13 comments

Comments

@ecorm
Copy link

ecorm commented Apr 3, 2020

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.

@HowardHinnant
Copy link
Owner

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> and namespace std::chrono, except format.

  • date::format is now std::format which follows the syntax/design of the fmt 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 of zoned_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 now January, 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 to hh_mm_ss. The name hh_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 of hh_mm_ss. For example instead of:

auto tod = make_time(tp-sd);

one writes:

hh_mm_ss tod{tp-sd};
  • leap was renamed to leap_seconds. Both names are present in the date lib so that you can transition prior to C++20.

  • link was renamed to time_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.

@ecorm
Copy link
Author

ecorm commented Apr 4, 2020

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?

@HowardHinnant
Copy link
Owner

global: http://eel.is/c++draft/time.format#2

@ecorm
Copy link
Author

ecorm commented Apr 4, 2020

Thanks, I incorrectly assumed the standard format overloads not taking a locale were locale-independent (which is different from the fmt library).

@ecorm
Copy link
Author

ecorm commented Apr 13, 2020

Other differences:

  • date::format throws std::ios_base::failure whereas std::format throws std::format_error.
  • No "exotic" clock types (such as utc_clock) in date library (oops, they're in tz.h -- see comment below).

@HowardHinnant
Copy link
Owner

Actually utc_clock, tai_clock and gps_clock are in tz.h. But file_clock is not in this library.

@bxparks
Copy link

bxparks commented Jun 10, 2020

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

@HowardHinnant
Copy link
Owner

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).

@ecorm
Copy link
Author

ecorm commented Jun 10, 2020

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.

@ecorm
Copy link
Author

ecorm commented Jul 15, 2021

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)

@QuantDevHacks
Copy link

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.

@zlojvavan
Copy link

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

@jjerphan
Copy link

The literal operators also are different and are _-prefixed:

date/include/date/date.h

Lines 1968 to 1987 in 1ead671

#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
inline namespace literals
{
CONSTCD11
inline
date::day
operator "" _d(unsigned long long d) NOEXCEPT
{
return date::day{static_cast<unsigned>(d)};
}
CONSTCD11
inline
date::year
operator "" _y(unsigned long long y) NOEXCEPT
{
return date::year(static_cast<int>(y));
}
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants