Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 35 additions & 20 deletions stl/inc/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -5498,10 +5498,10 @@ namespace chrono {
} else {
_Write_fractional_seconds<_Fractional_width>(_Os, _Hms.seconds(), _Hms.subseconds());
}
return;
} else {
const auto _Dp = _CHRONO floor<days>(_Val);
_Write_seconds(_Os, hh_mm_ss{_Val - _Dp});
}
const auto _Dp = _CHRONO floor<days>(_Val);
_Write_seconds(_Os, hh_mm_ss{_Val - _Dp});
}

template <class _CharT, class _Traits, class _Duration>
Expand Down Expand Up @@ -5848,7 +5848,7 @@ namespace chrono {
return _Res_iter;
}

void _Check_modifier(const char _Type, const char _Modifier) {
static void _Check_modifier(const char _Type, const char _Modifier) {
if (_Modifier == '\0') {
return;
}
Expand Down Expand Up @@ -5894,7 +5894,7 @@ namespace chrono {
}

template <class _Ty>
_NODISCARD constexpr bool _Is_valid_type(const char _Type) noexcept {
_NODISCARD static constexpr bool _Is_valid_type(const char _Type) noexcept {
if constexpr (_Is_specialization_v<_Ty, duration>) {
return _Type == 'j' || _Type == 'q' || _Type == 'Q' || _Is_valid_type<hh_mm_ss<seconds>>(_Type);
} else if constexpr (is_same_v<_Ty, day>) {
Expand All @@ -5910,11 +5910,12 @@ namespace chrono {
} else if constexpr (_Is_any_of_v<_Ty, month_weekday, month_weekday_last>) {
return _Is_valid_type<month>(_Type) || _Is_valid_type<weekday>(_Type);
} else if constexpr (is_same_v<_Ty, year_month>) {
return _Is_valid_type<year>(_Type) || _Is_valid_type<month>(_Type);
return _Type == 'g' || _Type == 'G' || _Is_valid_type<year>(_Type) || _Is_valid_type<month>(_Type);
} else if constexpr (_Is_any_of_v<_Ty, year_month_day, year_month_day_last, year_month_weekday,
year_month_weekday_last>) {
return _Type == 'D' || _Type == 'F' || _Type == 'j' || _Is_valid_type<year>(_Type)
|| _Is_valid_type<month>(_Type) || _Is_valid_type<day>(_Type) || _Is_valid_type<weekday>(_Type);
return _Type == 'D' || _Type == 'F' || _Type == 'g' || _Type == 'G' || _Type == 'j' || _Type == 'U'
|| _Type == 'V' || _Type == 'W' || _Is_valid_type<year>(_Type) || _Is_valid_type<month>(_Type)
|| _Is_valid_type<day>(_Type) || _Is_valid_type<weekday>(_Type);
} else if constexpr (_Is_specialization_v<_Ty, hh_mm_ss>) {
return _Type == 'H' || _Type == 'I' || _Type == 'M' || _Type == 'S' || _Type == 'r' || _Type == 'R'
|| _Type == 'T' || _Type == 'p';
Expand Down Expand Up @@ -6031,19 +6032,32 @@ namespace chrono {
}
_Os << _Time.tm_mday;
return true;
case 'r':
if constexpr (_Is_specialization_v<_Ty, hh_mm_ss>) {
// put_time uses _Strftime in order to bypass reference-counting that locale uses. This function
// takes the locale information by pointer, but the pointer (from _Gettnames) returns a copy.
// _Strftime delegates to other functions but eventually (for the C locale) has the %r specifier
// rewritten. It checks for the locale by comparing pointers, which do not compare equal as we have
// a copy of the pointer instead of the original. Therefore, we replace %r for the C locale
// ourselves.
if (_Os.getloc() == locale::classic()) {
_Os << _STD put_time(&_Time, _STATICALLY_WIDEN(_CharT, "%I:%M:%S %p"));
return true;
case 'g':
case 'G':
if constexpr (is_same_v<_Ty, year_month>) {
if (_Val.month() == January || _Val.month() == December) {
_THROW(format_error(
"The ISO week-based year for a year_month of January or December is ambiguous."));
}

const char _Gregorian_type = _Spec._Type == 'g' ? 'y' : 'Y';
_Os << _STD put_time(&_Time, _Fmt_string({._Type = _Gregorian_type}).data());
return true;
}

return false;
case 'r':
// put_time uses _Strftime in order to bypass reference-counting that locale uses. This function
// takes the locale information by pointer, but the pointer (from _Gettnames) returns a copy.
// _Strftime delegates to other functions but eventually (for the C locale) has the %r specifier
// rewritten. It checks for the locale by comparing pointers, which do not compare equal as we have
// a copy of the pointer instead of the original. Therefore, we replace %r for the C locale
// ourselves.
if (_Os.getloc() == locale::classic()) {
_Os << _STD put_time(&_Time, _STATICALLY_WIDEN(_CharT, "%I:%M:%S %p"));
return true;
}

return false;
case 'j':
if constexpr (_Is_specialization_v<_Ty, duration>) {
Expand All @@ -6058,6 +6072,7 @@ namespace chrono {
_THROW(format_error("The day of year for a month_day_last other than January is ambiguous"));
}
}

if constexpr (_Has_ok<_Ty>) {
if (!_Val.ok()) {
_THROW(format_error("Cannot print invalid day of year"));
Expand Down Expand Up @@ -6187,7 +6202,7 @@ namespace chrono {
}
}

_NODISCARD array<_CharT, 4> _Fmt_string(const _Chrono_spec<_CharT>& _Spec) {
_NODISCARD static array<_CharT, 4> _Fmt_string(const _Chrono_spec<_CharT>& _Spec) {
array<_CharT, 4> _Fmt_str;
size_t _Next_idx = 0;
_Fmt_str[_Next_idx++] = _CharT{'%'};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,24 @@ void test_clock_formatter() {
assert(format(STR("{:%Z %z %Oz %Ez}"), file_time<seconds>{}) == STR("UTC +0000 +00:00 +00:00"));
throw_helper(STR("{:%Z %z %Oz %Ez}"), local_seconds{});

assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / January / 1}) == STR("09 2009 00 53 00"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / January / 2}) == STR("09 2009 00 53 00"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / January / 3}) == STR("09 2009 01 53 00"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / January / 4}) == STR("10 2010 01 01 01"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / January / 5}) == STR("10 2010 01 01 01"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / January / 6}) == STR("10 2010 01 01 01"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / January / 7}) == STR("10 2010 01 01 01"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / May / 1}) == STR("10 2010 17 17 17"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / May / 2}) == STR("10 2010 18 17 17"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / May / 3}) == STR("10 2010 18 18 18"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / December / 25}) == STR("10 2010 51 51 51"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / December / 26}) == STR("10 2010 52 51 51"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / December / 27}) == STR("10 2010 52 52 52"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / December / 28}) == STR("10 2010 52 52 52"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / December / 29}) == STR("10 2010 52 52 52"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / December / 30}) == STR("10 2010 52 52 52"));
assert(format(STR("{:%g %G %U %V %W}"), sys_days{2010y / December / 31}) == STR("10 2010 52 52 52"));

assert(format(STR("{:%S}"), utc_clock::from_sys(get_tzdb().leap_seconds.front().date()) - 1s) == STR("60"));
assert(format(STR("{:%F %T}"), utc_clock::from_sys(get_tzdb().leap_seconds.front().date()))
== STR("1972-07-01 00:00:00"));
Expand Down Expand Up @@ -515,6 +533,13 @@ void test_year_month_formatter() {

assert(format(STR("{:%Y %B}"), 2000y / July) == STR("2000 July"));
throw_helper(STR("{:%d}"), 2000y / July);

throw_helper(STR("{:%g}"), 2005y / January);
throw_helper(STR("{:%G}"), 2005y / January);
assert(format(STR("{:%g %G}"), 2005y / February) == STR("05 2005"));
assert(format(STR("{:%g %G}"), 2005y / November) == STR("05 2005"));
throw_helper(STR("{:%g}"), 2005y / December);
throw_helper(STR("{:%G}"), 2005y / December);
}

template <typename CharT>
Expand All @@ -533,6 +558,24 @@ void test_year_month_day_formatter() {
assert(format(STR("{:%j}"), 1900y / May / 7) == STR("127"));
assert(format(STR("{:%j}"), 2000y / May / 7) == STR("128"));
throw_helper(STR("{:%j}"), invalid);

assert(format(STR("{:%g %G %U %V %W}"), 2010y / January / 1) == STR("09 2009 00 53 00"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / January / 2) == STR("09 2009 00 53 00"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / January / 3) == STR("09 2009 01 53 00"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / January / 4) == STR("10 2010 01 01 01"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / January / 5) == STR("10 2010 01 01 01"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / January / 6) == STR("10 2010 01 01 01"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / January / 7) == STR("10 2010 01 01 01"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / May / 1) == STR("10 2010 17 17 17"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / May / 2) == STR("10 2010 18 17 17"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / May / 3) == STR("10 2010 18 18 18"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / December / 25) == STR("10 2010 51 51 51"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / December / 26) == STR("10 2010 52 51 51"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / December / 27) == STR("10 2010 52 52 52"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / December / 28) == STR("10 2010 52 52 52"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / December / 29) == STR("10 2010 52 52 52"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / December / 30) == STR("10 2010 52 52 52"));
assert(format(STR("{:%g %G %U %V %W}"), 2010y / December / 31) == STR("10 2010 52 52 52"));
}

template <typename CharT>
Expand All @@ -557,6 +600,8 @@ void test_year_month_day_last_formatter() {
assert(format(STR("{:%j}"), 1900y / February / last) == STR("059"));
assert(format(STR("{:%j}"), 2000y / February / last) == STR("060"));
throw_helper(STR("{:%j}"), year{1900} / month{13} / last);

assert(format(STR("{:%g %G %U %V %W}"), 2010y / May / last) == STR("10 2010 22 22 22"));
}

template <typename CharT>
Expand Down Expand Up @@ -586,6 +631,8 @@ void test_year_month_weekday_formatter() {

assert(format(STR("{:%j}"), 1900y / January / Tuesday[2]) == STR("009"));
throw_helper(STR("{:%j}"), invalid1);

assert(format(STR("{:%g %G %U %V %W}"), 2010y / May / Monday[5]) == STR("10 2010 22 22 22"));
}

template <typename CharT>
Expand Down Expand Up @@ -613,6 +660,8 @@ void test_year_month_weekday_last_formatter() {

assert(format(STR("{:%j}"), 1900y / January / Tuesday[last]) == STR("030"));
throw_helper(STR("{:%j}"), invalid1);

assert(format(STR("{:%g %G %U %V %W}"), 2010y / May / Monday[last]) == STR("10 2010 22 22 22"));
}

template <typename CharT>
Expand Down Expand Up @@ -798,7 +847,8 @@ void test_local_time_format_formatter() {
assert(format(STR("{:%c, %x, %X}"), ltf) == STR("04/19/21 01:02:03, 04/19/21, 01:02:03"));
assert(format(STR("{:%D %F, %Y %C %y, %b %B %h %m, %d %e, %a %A %u %w}"), ltf)
== STR("04/19/21 2021-04-19, 2021 20 21, Apr April Apr 04, 19 19, Mon Monday 1 1"));
assert(format(STR("{:%H %I %M %S %r %R %T %p}"), ltf) == STR("01 01 02 03 01:02:03 01:02 01:02:03 AM"));
assert(format(STR("{:%H %I %M %S, %r, %R %T %p}"), ltf) == STR("01 01 02 03, 01:02:03 AM, 01:02 01:02:03 AM"));
assert(format(STR("{:%g %G %U %V %W}"), ltf) == STR("21 2021 16 16 16"));
}

template <typename CharT>
Expand All @@ -812,7 +862,8 @@ void test_zoned_time_formatter() {
assert(format(STR("{:%c, %x, %X}"), zt) == STR("04/19/21 08:16:17, 04/19/21, 08:16:17"));
assert(format(STR("{:%D %F, %Y %C %y, %b %B %h %m, %d %e, %a %A %u %w}"), zt)
== STR("04/19/21 2021-04-19, 2021 20 21, Apr April Apr 04, 19 19, Mon Monday 1 1"));
assert(format(STR("{:%H %I %M %S %r %R %T %p}"), zt) == STR("08 08 16 17 08:16:17 08:16 08:16:17 AM"));
assert(format(STR("{:%H %I %M %S, %r, %R %T %p}"), zt) == STR("08 08 16 17, 08:16:17 AM, 08:16 08:16:17 AM"));
assert(format(STR("{:%g %G %U %V %W}"), zt) == STR("21 2021 16 16 16"));
}

int main() {
Expand Down