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
61 changes: 37 additions & 24 deletions stl/inc/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -5239,6 +5239,7 @@ struct _Chrono_format_specs {
int _Dynamic_precision_index = -1;
_Fmt_align _Alignment = _Fmt_align::_None;
uint8_t _Fill_length = 1;
bool _Localized = false;
// At most one codepoint (so one char32_t or four utf-8 char8_t)
_CharT _Fill[4 / sizeof(_CharT)] = {_CharT{' '}};
// recursive definition in grammar, so could have any number of these
Expand Down Expand Up @@ -5294,6 +5295,10 @@ public:
_Specs._Dynamic_precision_index = _Verify_dynamic_arg_index_in_range(_Parse_ctx.next_arg_id());
}

constexpr void _On_localized() {
_Specs._Localized = true;
}

constexpr void _On_conversion_spec(char _Modifier, _CharT _Type) {
// NOTE: same performance note from _Basic_format_specs also applies here
if (_Modifier != '\0' && _Modifier != 'E' && _Modifier != 'O') {
Expand Down Expand Up @@ -5375,6 +5380,14 @@ _NODISCARD constexpr const _CharT* _Parse_chrono_format_specs(
}
}

if (*_Begin == 'L') {
_Callbacks._On_localized();
++_Begin;
if (_Begin == _End) {
return _Begin;
}
}

if (*_Begin != '}' && *_Begin != '%') {
_THROW(format_error("Invalid format string - chrono-specs must begin with conversion-spec"));
}
Expand Down Expand Up @@ -5582,7 +5595,7 @@ namespace chrono {

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const month& _Val) {
return _Os << (_Val.ok() ? _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:%b}"), _Val)
return _Os << (_Val.ok() ? _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%b}"), _Val)
: _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{} is not a valid month"),
static_cast<unsigned int>(_Val)));
}
Expand All @@ -5595,7 +5608,7 @@ namespace chrono {

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const weekday& _Val) {
return _Os << (_Val.ok() ? _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:%a}"), _Val)
return _Os << (_Val.ok() ? _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%a}"), _Val)
: _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{} is not a valid weekday"),
_Val.c_encoding()));
}
Expand All @@ -5604,40 +5617,41 @@ namespace chrono {
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const weekday_indexed& _Val) {
const auto _Idx = _Val.index();
return _Os << (_Idx >= 1 && _Idx <= 5
? _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}[{}]"), _Val.weekday(), _Idx)
: _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}[{} is not a valid index]"),
? _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L}[{}]"), _Val.weekday(), _Idx)
: _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L}[{} is not a valid index]"),
_Val.weekday(), _Idx));
}

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const weekday_last& _Val) {
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}[last]"), _Val.weekday());
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L}[last]"), _Val.weekday());
}

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const month_day& _Val) {
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{}"), _Val.month(), _Val.day());
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L}/{}"), _Val.month(), _Val.day());
}

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const month_day_last& _Val) {
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/last"), _Val.month());
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L}/last"), _Val.month());
}

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const month_weekday& _Val) {
return _Os << _STD format(
_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{}"), _Val.month(), _Val.weekday_indexed());
_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), _Val.month(), _Val.weekday_indexed());
}

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const month_weekday_last& _Val) {
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{}"), _Val.month(), _Val.weekday_last());
return _Os << _STD format(
_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), _Val.month(), _Val.weekday_last());
}

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const year_month& _Val) {
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{}"), _Val.year(), _Val.month());
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{:L}"), _Val.year(), _Val.month());
}

template <class _CharT, class _Traits>
Expand All @@ -5648,25 +5662,26 @@ namespace chrono {

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const year_month_day_last& _Val) {
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{}"), _Val.year(), _Val.month_day_last());
return _Os << _STD format(
_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{:L}"), _Val.year(), _Val.month_day_last());
}

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const year_month_weekday& _Val) {
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{}/{}"), _Val.year(), _Val.month(),
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), _Val.year(), _Val.month(),
_Val.weekday_indexed());
}

template <class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>& operator<<(
basic_ostream<_CharT, _Traits>& _Os, const year_month_weekday_last& _Val) {
return _Os << _STD format(
_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{}/{}"), _Val.year(), _Val.month(), _Val.weekday_last());
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), _Val.year(), _Val.month(),
_Val.weekday_last());
}

template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const hh_mm_ss<_Duration>& _Val) {
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:%T}"), _Val);
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%T}"), _Val);
}

#pragma warning(push)
Expand Down Expand Up @@ -5715,9 +5730,7 @@ namespace chrono {
requires (!treat_as_floating_point_v<typename _Duration::rep> && _Duration{1} < days{1})
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const sys_time<_Duration>& _Val) {
// clang-format on
const auto _Dp = _CHRONO floor<days>(_Val);
return _Os << _STD format(
_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{} {}"), year_month_day{_Dp}, hh_mm_ss{_Val - _Dp});
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%F %T}"), _Val);
}

template <class _CharT, class _Traits>
Expand All @@ -5727,22 +5740,22 @@ namespace chrono {

template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const utc_time<_Duration>& _Val) {
return _Os << _STD format(_STATICALLY_WIDEN(_CharT, "{:%F %T}"), _Val);
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%F %T}"), _Val);
}

template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const tai_time<_Duration>& _Val) {
return _Os << _STD format(_STATICALLY_WIDEN(_CharT, "{:%F %T}"), _Val);
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%F %T}"), _Val);
}

template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const gps_time<_Duration>& _Val) {
return _Os << _STD format(_STATICALLY_WIDEN(_CharT, "{:%F %T}"), _Val);
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%F %T}"), _Val);
}

template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const file_time<_Duration>& _Val) {
return _Os << _STD format(_STATICALLY_WIDEN(_CharT, "{:%F %T}"), _Val);
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%F %T}"), _Val);
}

template <class _CharT, class _Traits, class _Duration>
Expand All @@ -5755,7 +5768,7 @@ namespace chrono {
basic_ostream<_CharT, _Traits>& _Os, const _Local_time_format_t<_Duration>& _Val) {
// Doesn't appear in the Standard, but allowed by N4885 [global.functions]/2.
// Implements N4885 [time.zone.zonedtime.nonmembers]/2 for zoned_time.
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:%F %T %Z}"), _Val);
return _Os << _STD format(_Os.getloc(), _STATICALLY_WIDEN(_CharT, "{:L%F %T %Z}"), _Val);
}

template <class _CharT, class _Traits, class _Duration, class _TimeZonePtr>
Expand Down Expand Up @@ -5899,10 +5912,10 @@ namespace chrono {
_NODISCARD auto _Write(_FormatContext& _FormatCtx, const _Ty& _Val, const tm& _Time) {
basic_ostringstream<_CharT> _Stream;

_Stream.imbue(_Specs._Localized ? _FormatCtx.locale() : locale::classic());
if (_Specs._Chrono_specs_list.empty()) {
_Stream << _Val; // N4885 [time.format]/6
} else {
_Stream.imbue(_FormatCtx.locale());
if constexpr (_Is_specialization_v<_Ty, hh_mm_ss>) {
if (_Val.is_negative()) {
_Stream << _CharT{'-'};
Expand Down
1 change: 1 addition & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@
// P2325R3 Views Should Not Be Required To Be Default Constructible
// P2328R1 join_view Should Join All views Of ranges
// P2367R0 Remove Misuses Of List-Initialization From Clause 24 Ranges
// P2372R3 Fixing Locale Handling In chrono Formatters
// P2432R1 Fix istream_view
// P????R? directory_entry::clear_cache()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct testing_callbacks {
int expected_precision = -1;
size_t expected_dynamic_precision = static_cast<size_t>(-1);
bool expected_auto_dynamic_precision = false;
bool expected_localized = false;
vector<_Chrono_spec<CharT>>& expected_chrono_specs;
size_t curr_index = 0;

Expand Down Expand Up @@ -75,6 +76,9 @@ struct testing_callbacks {
void _On_dynamic_precision(_Auto_id_tag) {
assert(expected_auto_dynamic_precision);
}
void _On_localized() {
assert(expected_localized);
}
void _On_conversion_spec(char mod, CharT type) {
assert(mod == expected_chrono_specs[curr_index]._Modifier);
assert(static_cast<char>(type) == expected_chrono_specs[curr_index]._Type);
Expand Down Expand Up @@ -152,6 +156,8 @@ bool test_parse_chrono_format_specs() {
view_typ s6(STR("%H%"));
view_typ s7(STR("%H%}"));
view_typ s8(STR("%nB%tC%%D"));
view_typ s9(STR("L"));
view_typ s10(STR("L%F"));

vector<chrono_spec> v0{{._Modifier = 'O', ._Type = 'e'}};
test_parse_helper(parse_chrono_format_specs_fn, s0, false, s0.size(), {.expected_chrono_specs = v0});
Expand Down Expand Up @@ -189,6 +195,15 @@ bool test_parse_chrono_format_specs() {
test_parse_helper(parse_chrono_format_specs_fn, s6, true, view_typ::npos, {.expected_chrono_specs = v});
test_parse_helper(parse_chrono_format_specs_fn, s7, true, view_typ::npos, {.expected_chrono_specs = v});

vector<chrono_spec> v_empty{};
test_parse_helper(parse_chrono_format_specs_fn, s9, false, view_typ::npos,
{.expected_localized = true, .expected_chrono_specs = v_empty});

vector<chrono_spec> v6{{._Type = 'F'}};
test_parse_helper(parse_chrono_format_specs_fn, s10, false, view_typ::npos,
{.expected_localized = true, .expected_chrono_specs = v6});


return true;
}

Expand Down Expand Up @@ -900,8 +915,34 @@ void test_zoned_time_formatter() {

template <typename CharT>
void test_locale() {
assert(format(locale{"zh-CN"}, STR("{:^22%Y %B %d %A}"), 2021y / June / 16d)
assert(format(locale{"zh-CN"}, STR("{:^22L%Y %B %d %A}"), 2021y / June / 16d)
== STR(" 2021 \u516D\u6708 16 \u661F\u671F\u4E09 "));


locale loc("de-DE");

assert(format(loc, STR("{:%S}"), 42ms) == STR("00.042"));
assert(format(loc, STR("{:L%S}"), 42ms) == STR("00,042"));

auto stream = [=](auto value) {
basic_ostringstream<CharT> os;
os.imbue(loc);
os << value;
return os.str();
};
assert(stream(month{May}) == STR("Mai"));
assert(stream(weekday{Tuesday}) == STR("Di"));
assert(stream(weekday_indexed{Tuesday[3]}) == STR("Di[3]"));
assert(stream(weekday_indexed{Tuesday[42]}) == STR("Di[42 is not a valid index]"));
assert(stream(weekday_last{Tuesday}) == STR("Di[last]"));
assert(stream(month_day{May, day{4}}) == STR("Mai/04"));
assert(stream(month_day_last{May}) == STR("Mai/last"));
assert(stream(month_weekday{May / Tuesday[4]}) == STR("Mai/Di[4]"));
assert(stream(month_weekday_last{May / Tuesday[last]}) == STR("Mai/Di[last]"));
assert(stream(year_month{2021y / May}) == STR("2021/Mai"));
assert(stream(year_month_day_last{2021y / May / last}) == STR("2021/Mai/last"));
assert(stream(year_month_weekday{2021y / May / Tuesday[4]}) == STR("2021/Mai/Di[4]"));
assert(stream(year_month_weekday_last{2021y / May / Tuesday[last]}) == STR("2021/Mai/Di[last]"));
}

void test() {
Expand Down