mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-12 07:10:15 +00:00
Add glibc ext for day of month and week of year (#3976)
This commit is contained in:
parent
cddb41f633
commit
ca8eeb09ee
@ -267,9 +267,10 @@ as `std::tm` have the following syntax:
|
|||||||
<pre>
|
<pre>
|
||||||
chrono_format_spec ::= [[<a href="#format-spec">fill</a>]<a href="#format-spec">align</a>][<a href="#format-spec">width</a>]["." <a href="#format-spec">precision</a>][chrono_specs]
|
chrono_format_spec ::= [[<a href="#format-spec">fill</a>]<a href="#format-spec">align</a>][<a href="#format-spec">width</a>]["." <a href="#format-spec">precision</a>][chrono_specs]
|
||||||
chrono_specs ::= [chrono_specs] conversion_spec | chrono_specs literal_char
|
chrono_specs ::= [chrono_specs] conversion_spec | chrono_specs literal_char
|
||||||
conversion_spec ::= "%" [modifier] chrono_type
|
conversion_spec ::= "%" [padding_modifier] [locale_modifier] chrono_type
|
||||||
literal_char ::= <a character other than '{', '}' or '%'>
|
literal_char ::= <a character other than '{', '}' or '%'>
|
||||||
modifier ::= "E" | "O"
|
padding_modifier ::= "-" | "_" | "0"
|
||||||
|
locale_modifier ::= "E" | "O"
|
||||||
chrono_type ::= "a" | "A" | "b" | "B" | "c" | "C" | "d" | "D" | "e" | "F" |
|
chrono_type ::= "a" | "A" | "b" | "B" | "c" | "C" | "d" | "D" | "e" | "F" |
|
||||||
"g" | "G" | "h" | "H" | "I" | "j" | "m" | "M" | "n" | "p" |
|
"g" | "G" | "h" | "H" | "I" | "j" | "m" | "M" | "n" | "p" |
|
||||||
"q" | "Q" | "r" | "R" | "S" | "t" | "T" | "u" | "U" | "V" |
|
"q" | "Q" | "r" | "R" | "S" | "t" | "T" | "u" | "U" | "V" |
|
||||||
@ -327,6 +328,17 @@ The available presentation types (*chrono_type*) are:
|
|||||||
Specifiers that have a calendaric component such as `'d'` (the day of
|
Specifiers that have a calendaric component such as `'d'` (the day of
|
||||||
month) are valid only for `std::tm` and time points but not durations.
|
month) are valid only for `std::tm` and time points but not durations.
|
||||||
|
|
||||||
|
The available padding modifiers (*padding_modifier*) are:
|
||||||
|
|
||||||
|
| Type | Meaning |
|
||||||
|
|-------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `'-'` | Pad a numeric result with spaces. |
|
||||||
|
| `'_'` | Do not pad a numeric result string. |
|
||||||
|
| `'0'` | Pad a numeric result string with zeros. |
|
||||||
|
|
||||||
|
Currently, these modifiers are only supported for the ``'H', 'I', 'M', 'S', 'U', 'V'``
|
||||||
|
and ``'W'`` presentation types.
|
||||||
|
|
||||||
## Range Format Specifications
|
## Range Format Specifications
|
||||||
|
|
||||||
Format specifications for range types have the following syntax:
|
Format specifications for range types have the following syntax:
|
||||||
|
@ -795,22 +795,22 @@ FMT_CONSTEXPR auto parse_chrono_format(const Char* begin, const Char* end,
|
|||||||
break;
|
break;
|
||||||
// Day of the year/month:
|
// Day of the year/month:
|
||||||
case 'U':
|
case 'U':
|
||||||
handler.on_dec0_week_of_year(numeric_system::standard);
|
handler.on_dec0_week_of_year(numeric_system::standard, pad);
|
||||||
break;
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
handler.on_dec1_week_of_year(numeric_system::standard);
|
handler.on_dec1_week_of_year(numeric_system::standard, pad);
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
handler.on_iso_week_of_year(numeric_system::standard);
|
handler.on_iso_week_of_year(numeric_system::standard, pad);
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
handler.on_day_of_year();
|
handler.on_day_of_year();
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
handler.on_day_of_month(numeric_system::standard);
|
handler.on_day_of_month(numeric_system::standard, pad);
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
handler.on_day_of_month_space(numeric_system::standard);
|
handler.on_day_of_month(numeric_system::standard, pad_type::space);
|
||||||
break;
|
break;
|
||||||
// Hour, minute, second:
|
// Hour, minute, second:
|
||||||
case 'H':
|
case 'H':
|
||||||
@ -907,19 +907,19 @@ FMT_CONSTEXPR auto parse_chrono_format(const Char* begin, const Char* end,
|
|||||||
handler.on_dec_month(numeric_system::alternative);
|
handler.on_dec_month(numeric_system::alternative);
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
handler.on_dec0_week_of_year(numeric_system::alternative);
|
handler.on_dec0_week_of_year(numeric_system::alternative, pad);
|
||||||
break;
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
handler.on_dec1_week_of_year(numeric_system::alternative);
|
handler.on_dec1_week_of_year(numeric_system::alternative, pad);
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
handler.on_iso_week_of_year(numeric_system::alternative);
|
handler.on_iso_week_of_year(numeric_system::alternative, pad);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
handler.on_day_of_month(numeric_system::alternative);
|
handler.on_day_of_month(numeric_system::alternative, pad);
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
handler.on_day_of_month_space(numeric_system::alternative);
|
handler.on_day_of_month(numeric_system::alternative, pad_type::space);
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
handler.on_dec0_weekday(numeric_system::alternative);
|
handler.on_dec0_weekday(numeric_system::alternative);
|
||||||
@ -972,12 +972,19 @@ template <typename Derived> struct null_chrono_spec_handler {
|
|||||||
FMT_CONSTEXPR void on_abbr_month() { unsupported(); }
|
FMT_CONSTEXPR void on_abbr_month() { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_full_month() { unsupported(); }
|
FMT_CONSTEXPR void on_full_month() { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_dec_month(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_dec_month(numeric_system) { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system, pad_type) {
|
||||||
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) { unsupported(); }
|
unsupported();
|
||||||
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) { unsupported(); }
|
}
|
||||||
|
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system, pad_type) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system, pad_type) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
FMT_CONSTEXPR void on_day_of_year() { unsupported(); }
|
FMT_CONSTEXPR void on_day_of_year() { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_day_of_month(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_day_of_month(numeric_system, pad_type) {
|
||||||
FMT_CONSTEXPR void on_day_of_month_space(numeric_system) { unsupported(); }
|
unsupported();
|
||||||
|
}
|
||||||
FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); }
|
||||||
@ -1015,12 +1022,11 @@ struct tm_format_checker : null_chrono_spec_handler<tm_format_checker> {
|
|||||||
FMT_CONSTEXPR void on_abbr_month() {}
|
FMT_CONSTEXPR void on_abbr_month() {}
|
||||||
FMT_CONSTEXPR void on_full_month() {}
|
FMT_CONSTEXPR void on_full_month() {}
|
||||||
FMT_CONSTEXPR void on_dec_month(numeric_system) {}
|
FMT_CONSTEXPR void on_dec_month(numeric_system) {}
|
||||||
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) {}
|
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system, pad_type) {}
|
||||||
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) {}
|
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system, pad_type) {}
|
||||||
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) {}
|
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system, pad_type) {}
|
||||||
FMT_CONSTEXPR void on_day_of_year() {}
|
FMT_CONSTEXPR void on_day_of_year() {}
|
||||||
FMT_CONSTEXPR void on_day_of_month(numeric_system) {}
|
FMT_CONSTEXPR void on_day_of_month(numeric_system, pad_type) {}
|
||||||
FMT_CONSTEXPR void on_day_of_month_space(numeric_system) {}
|
|
||||||
FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type) {}
|
FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type) {}
|
||||||
FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type) {}
|
FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type) {}
|
||||||
FMT_CONSTEXPR void on_minute(numeric_system, pad_type) {}
|
FMT_CONSTEXPR void on_minute(numeric_system, pad_type) {}
|
||||||
@ -1454,7 +1460,7 @@ class tm_writer {
|
|||||||
*out_++ = ' ';
|
*out_++ = ' ';
|
||||||
on_abbr_month();
|
on_abbr_month();
|
||||||
*out_++ = ' ';
|
*out_++ = ' ';
|
||||||
on_day_of_month_space(numeric_system::standard);
|
on_day_of_month(numeric_system::standard, pad_type::space);
|
||||||
*out_++ = ' ';
|
*out_++ = ' ';
|
||||||
on_iso_time();
|
on_iso_time();
|
||||||
*out_++ = ' ';
|
*out_++ = ' ';
|
||||||
@ -1541,24 +1547,26 @@ class tm_writer {
|
|||||||
format_localized('m', 'O');
|
format_localized('m', 'O');
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_dec0_week_of_year(numeric_system ns) {
|
void on_dec0_week_of_year(numeric_system ns, pad_type pad) {
|
||||||
if (is_classic_ || ns == numeric_system::standard)
|
if (is_classic_ || ns == numeric_system::standard)
|
||||||
return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week);
|
return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week,
|
||||||
|
pad);
|
||||||
format_localized('U', 'O');
|
format_localized('U', 'O');
|
||||||
}
|
}
|
||||||
void on_dec1_week_of_year(numeric_system ns) {
|
void on_dec1_week_of_year(numeric_system ns, pad_type pad) {
|
||||||
if (is_classic_ || ns == numeric_system::standard) {
|
if (is_classic_ || ns == numeric_system::standard) {
|
||||||
auto wday = tm_wday();
|
auto wday = tm_wday();
|
||||||
write2((tm_yday() + days_per_week -
|
write2((tm_yday() + days_per_week -
|
||||||
(wday == 0 ? (days_per_week - 1) : (wday - 1))) /
|
(wday == 0 ? (days_per_week - 1) : (wday - 1))) /
|
||||||
days_per_week);
|
days_per_week,
|
||||||
|
pad);
|
||||||
} else {
|
} else {
|
||||||
format_localized('W', 'O');
|
format_localized('W', 'O');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void on_iso_week_of_year(numeric_system ns) {
|
void on_iso_week_of_year(numeric_system ns, pad_type pad) {
|
||||||
if (is_classic_ || ns == numeric_system::standard)
|
if (is_classic_ || ns == numeric_system::standard)
|
||||||
return write2(tm_iso_week_of_year());
|
return write2(tm_iso_week_of_year(), pad);
|
||||||
format_localized('V', 'O');
|
format_localized('V', 'O');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1572,20 +1580,11 @@ class tm_writer {
|
|||||||
write1(yday / 100);
|
write1(yday / 100);
|
||||||
write2(yday % 100);
|
write2(yday % 100);
|
||||||
}
|
}
|
||||||
void on_day_of_month(numeric_system ns) {
|
void on_day_of_month(numeric_system ns, pad_type pad) {
|
||||||
if (is_classic_ || ns == numeric_system::standard) return write2(tm_mday());
|
if (is_classic_ || ns == numeric_system::standard)
|
||||||
|
return write2(tm_mday(), pad);
|
||||||
format_localized('d', 'O');
|
format_localized('d', 'O');
|
||||||
}
|
}
|
||||||
void on_day_of_month_space(numeric_system ns) {
|
|
||||||
if (is_classic_ || ns == numeric_system::standard) {
|
|
||||||
auto mday = to_unsigned(tm_mday()) % 100;
|
|
||||||
const char* d2 = digits2(mday);
|
|
||||||
*out_++ = mday < 10 ? ' ' : d2[0];
|
|
||||||
*out_++ = d2[1];
|
|
||||||
} else {
|
|
||||||
format_localized('e', 'O');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_24_hour(numeric_system ns, pad_type pad) {
|
void on_24_hour(numeric_system ns, pad_type pad) {
|
||||||
if (is_classic_ || ns == numeric_system::standard)
|
if (is_classic_ || ns == numeric_system::standard)
|
||||||
@ -1933,11 +1932,10 @@ struct chrono_formatter {
|
|||||||
void on_iso_week_based_year() {}
|
void on_iso_week_based_year() {}
|
||||||
void on_iso_week_based_short_year() {}
|
void on_iso_week_based_short_year() {}
|
||||||
void on_dec_month(numeric_system) {}
|
void on_dec_month(numeric_system) {}
|
||||||
void on_dec0_week_of_year(numeric_system) {}
|
void on_dec0_week_of_year(numeric_system, pad_type) {}
|
||||||
void on_dec1_week_of_year(numeric_system) {}
|
void on_dec1_week_of_year(numeric_system, pad_type) {}
|
||||||
void on_iso_week_of_year(numeric_system) {}
|
void on_iso_week_of_year(numeric_system, pad_type) {}
|
||||||
void on_day_of_month(numeric_system) {}
|
void on_day_of_month(numeric_system, pad_type) {}
|
||||||
void on_day_of_month_space(numeric_system) {}
|
|
||||||
|
|
||||||
void on_day_of_year() {
|
void on_day_of_year() {
|
||||||
if (handle_nan_inf()) return;
|
if (handle_nan_inf()) return;
|
||||||
@ -2156,7 +2154,8 @@ struct formatter<day, Char> : private formatter<std::tm, Char> {
|
|||||||
if (use_tm_formatter_) return formatter<std::tm, Char>::format(time, ctx);
|
if (use_tm_formatter_) return formatter<std::tm, Char>::format(time, ctx);
|
||||||
detail::get_locale loc(false, ctx.locale());
|
detail::get_locale loc(false, ctx.locale());
|
||||||
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
|
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
|
||||||
w.on_day_of_month(detail::numeric_system::standard);
|
w.on_day_of_month(detail::numeric_system::standard,
|
||||||
|
detail::pad_type::unspecified);
|
||||||
return w.out();
|
return w.out();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1004,12 +1004,32 @@ TEST(chrono_test, glibc_extensions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto d = std::chrono::duration<double>(3.14);
|
auto d = std::chrono::duration<double>(3.14);
|
||||||
EXPECT_EQ(fmt::format("{:%S}", d), "03.140000");
|
EXPECT_EQ(fmt::format("{:%S}", d), "03.140000");
|
||||||
EXPECT_EQ(fmt::format("{:%0S}", d), "03.140000");
|
EXPECT_EQ(fmt::format("{:%0S}", d), "03.140000");
|
||||||
EXPECT_EQ(fmt::format("{:%_S}", d), " 3.140000");
|
EXPECT_EQ(fmt::format("{:%_S}", d), " 3.140000");
|
||||||
EXPECT_EQ(fmt::format("{:%-S}", d), "3.140000");
|
EXPECT_EQ(fmt::format("{:%-S}", d), "3.140000");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto t = std::tm();
|
||||||
|
t.tm_yday = 7;
|
||||||
|
EXPECT_EQ(fmt::format("{:%U,%W,%V}", t), "02,01,01");
|
||||||
|
EXPECT_EQ(fmt::format("{:%0U,%0W,%0V}", t), "02,01,01");
|
||||||
|
EXPECT_EQ(fmt::format("{:%_U,%_W,%_V}", t), " 2, 1, 1");
|
||||||
|
EXPECT_EQ(fmt::format("{:%-U,%-W,%-V}", t), "2,1,1");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto t = std::tm();
|
||||||
|
t.tm_mday = 7;
|
||||||
|
EXPECT_EQ(fmt::format("{:%d}", t), "07");
|
||||||
|
EXPECT_EQ(fmt::format("{:%0d}", t), "07");
|
||||||
|
EXPECT_EQ(fmt::format("{:%_d}", t), " 7");
|
||||||
|
EXPECT_EQ(fmt::format("{:%-d}", t), "7");
|
||||||
|
|
||||||
|
EXPECT_EQ(fmt::format("{:%e}", t), " 7");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(chrono_test, out_of_range) {
|
TEST(chrono_test, out_of_range) {
|
||||||
|
Loading…
Reference in New Issue
Block a user