
- Add an example with a local locale - Add links to documentation - Correct a few typos - I did not add an independent example using the global locale but added a comment
104 lines
3.3 KiB
Plaintext
104 lines
3.3 KiB
Plaintext
== Why is this an issue?
|
|
|
|
The ``++chrono++`` library, introduced in {cpp}20, provides support for calendars, time zones, and i/o formatting and parsing operations on time-related objects.
|
|
|
|
|
|
``++chrono++`` is a better alternative to the C/POSIX functions that operate on ``++time_t++``, ``++tm++``, or ``++timespec++`` types. In comparison to C facilities, it provides better integration with other components of the {cpp} standard library (``++iostreams++`` and ``++format++``). Also, it supports compile-time computation and it is thread-safe.
|
|
|
|
|
|
This rule raises an issue C/POSIX functions that can be replaced with one of the ``++std::chrono++`` components:
|
|
|
|
* querying for current time (``++time++``, ``++timespec_get++``, ``++clock_gettime++``)
|
|
* date to time-point conversion (``++mktime++``, ``++gmtime++``, ``++localtime++``)
|
|
* time serialization (``++ctime++``, ``++asctime++``, ``++strftime++``)
|
|
* time parsing (``++strptime++``)
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,cpp]
|
|
----
|
|
int currentMonth() {
|
|
std::time_t tp;
|
|
std::time(&tp);
|
|
std::tm* date = std::gmtime(&tp);
|
|
return date->tm_mon + 1;
|
|
}
|
|
|
|
std::chrono::system_clock::time_point makeSomeDay() {
|
|
// Creates time_point corresponding to 2020-09-04
|
|
std::tm date{};
|
|
date.tm_year = 120;
|
|
date.tm_mon = 8;
|
|
date.tm_mday = 4;
|
|
std::time_t t = std::mktime(&date); // Noncompliant
|
|
return std::chrono::system_clock::from_time_t(t);
|
|
}
|
|
|
|
std::optional<int> yearOfTimePoint(std::chrono::system_clock::time_point tp) {
|
|
std::time_t t = std::chrono::system_clock::to_time_t(tp);
|
|
std::tm* date = std::gmtime(&t); // Noncompliant
|
|
if (!date)
|
|
return std::nullopt;
|
|
return date->tm_year + 1900;
|
|
}
|
|
|
|
std::string toString(std::chrono::system_clock::time_point tp) {
|
|
std::time_t t = std::chrono::system_clock::to_time_t(tp);
|
|
std::tm* date = std::gmtime(&t); // Noncompliant
|
|
if (!date)
|
|
throw InvalidDate();
|
|
|
|
std::string buffer(100, ' ');
|
|
std::size_t written = std::strftime(&buffer[0], buffer.size(), "%A %c", date);
|
|
buffer.resize(written);
|
|
return buffer;
|
|
}
|
|
|
|
std::string toFrenchString(std::chrono::system_clock::time_point tp) {
|
|
auto oldLocale = std::locale::global(std::locale("fr_FR.UTF-8"));
|
|
std::string result = toString(tp);
|
|
std::locale::global(oldLocale);
|
|
return result;
|
|
}
|
|
----
|
|
|
|
=== Compliant solution
|
|
|
|
[source,cpp]
|
|
----
|
|
std::chrono::month currentMonth() {
|
|
using namespace std::chrono;
|
|
auto dp = floor<days>(system_clock::now());
|
|
return year_month_day(dp).month();
|
|
}
|
|
|
|
std::chrono::system_clock::time_point makeSomeDay() {
|
|
using namespace std::chrono;
|
|
return sys_days(2020y/September/4);
|
|
}
|
|
|
|
std::optional<std::chrono::year> yearOfTimePoint(std::chrono::system_clock::time_point tp) {
|
|
using namespace std::chrono;
|
|
year_month_day date(floor<days>(tp));
|
|
if (!date.ok())
|
|
return std::nullopt;
|
|
return date.year();
|
|
}
|
|
|
|
std::string toString(std::chrono::system_clock::time_point tp) {
|
|
return std::format("{:%A %c}", tp); // Or "{:L%A %c}" if you want to use the global locale
|
|
}
|
|
|
|
std::string toFrenchString(std::chrono::system_clock::time_point tp) {
|
|
return std::format(std::locale("fr_FR.UTF-8"), "{:L%A %c}", tp);
|
|
}
|
|
----
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* {cpp} reference - https://en.cppreference.com/w/cpp/chrono[Date and time utilities]
|
|
* {cpp} reference - https://en.cppreference.com/w/cpp/chrono/system_clock/formatter#Format_specification[Formatting `std::chrono::sys_time`]
|
|
|