mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-24 12:14:26 +00:00
More chrono formatting
This commit is contained in:
parent
aa3b5aba41
commit
628f830583
@ -31,6 +31,7 @@ inline null<> gmtime_s(...) { return null<>(); }
|
||||
|
||||
enum class numeric_system {
|
||||
standard,
|
||||
// Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale.
|
||||
alternative
|
||||
};
|
||||
|
||||
@ -64,10 +65,10 @@ FMT_CONSTEXPR const Char *parse_chrono_format(
|
||||
handler.on_full_weekday();
|
||||
break;
|
||||
case 'w':
|
||||
handler.on_dec0_weekday();
|
||||
handler.on_dec0_weekday(numeric_system::standard);
|
||||
break;
|
||||
case 'u':
|
||||
handler.on_dec1_weekday();
|
||||
handler.on_dec1_weekday(numeric_system::standard);
|
||||
break;
|
||||
// Month:
|
||||
case 'b':
|
||||
@ -95,6 +96,12 @@ FMT_CONSTEXPR const Char *parse_chrono_format(
|
||||
throw format_error("invalid format");
|
||||
c = *ptr++;
|
||||
switch (c) {
|
||||
case 'w':
|
||||
handler.on_dec0_weekday(numeric_system::alternative);
|
||||
break;
|
||||
case 'u':
|
||||
handler.on_dec1_weekday(numeric_system::alternative);
|
||||
break;
|
||||
case 'H':
|
||||
handler.on_24_hour(numeric_system::alternative);
|
||||
break;
|
||||
@ -123,8 +130,8 @@ struct chrono_format_checker {
|
||||
void on_text(const Char *, const Char *) {}
|
||||
void on_abbr_weekday() {}
|
||||
void on_full_weekday() {}
|
||||
void on_dec0_weekday() {}
|
||||
void on_dec1_weekday() {}
|
||||
void on_dec0_weekday(numeric_system) {}
|
||||
void on_dec1_weekday(numeric_system) {}
|
||||
void on_abbr_month() {}
|
||||
void on_full_month() {}
|
||||
void on_24_hour(numeric_system) {}
|
||||
@ -158,8 +165,8 @@ struct chrono_formatter {
|
||||
|
||||
void write(int value, int width) {
|
||||
typedef typename int_traits<int>::main_type main_type;
|
||||
main_type n = value;
|
||||
int num_digits = internal::count_digits(n);
|
||||
main_type n = to_unsigned(value);
|
||||
int num_digits = static_cast<int>(internal::count_digits(n));
|
||||
if (width > num_digits)
|
||||
out = std::fill_n(out, width - num_digits, '0');
|
||||
out = format_decimal<char_type>(out, n, num_digits);
|
||||
@ -182,8 +189,8 @@ struct chrono_formatter {
|
||||
|
||||
void on_abbr_weekday() {}
|
||||
void on_full_weekday() {}
|
||||
void on_dec0_weekday() {}
|
||||
void on_dec1_weekday() {}
|
||||
void on_dec0_weekday(numeric_system) {}
|
||||
void on_dec1_weekday(numeric_system) {}
|
||||
void on_abbr_month() {}
|
||||
void on_full_month() {}
|
||||
|
||||
@ -211,16 +218,23 @@ struct chrono_formatter {
|
||||
if (ns == numeric_system::standard)
|
||||
return write(minute, 2);
|
||||
auto time = tm();
|
||||
time.tm_minute = minute;
|
||||
time.tm_min = minute;
|
||||
format_localized(time, 'M');
|
||||
}
|
||||
|
||||
void on_second(numeric_system) {
|
||||
write(to_int(s.count() % 60), 2);
|
||||
if (ms != std::chrono::milliseconds()) {
|
||||
*out++ = '.';
|
||||
write(to_int(ms.count()), 3);
|
||||
void on_second(numeric_system ns) {
|
||||
auto second = to_int(s.count() % 60);
|
||||
if (ns == numeric_system::standard) {
|
||||
write(second, 2);
|
||||
if (ms != std::chrono::milliseconds()) {
|
||||
*out++ = '.';
|
||||
write(to_int(ms.count()), 3);
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto time = tm();
|
||||
time.tm_sec = second;
|
||||
format_localized(time, 'S');
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
@ -82,6 +82,22 @@ TEST(TimeTest, Chrono) {
|
||||
fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345)));
|
||||
}
|
||||
|
||||
std::string format_tm(const std::tm &time, const char *spec,
|
||||
const std::locale &loc) {
|
||||
std::ostringstream os;
|
||||
os.imbue(loc);
|
||||
os << std::put_time(&time, spec);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
#define EXPECT_TIME(spec, field, value, duration) { \
|
||||
auto time = std::tm(); \
|
||||
time.field = value; \
|
||||
std::locale("ja_JP.utf8"); \
|
||||
EXPECT_EQ(format_tm(time, spec, loc), \
|
||||
fmt::format(loc, "{:" spec "}", std::chrono::duration(value))); \
|
||||
}
|
||||
|
||||
TEST(TimeTest, ChronoLocale) {
|
||||
const char *loc_name = "ja_JP.utf8";
|
||||
bool has_locale = false;
|
||||
@ -94,21 +110,9 @@ TEST(TimeTest, ChronoLocale) {
|
||||
fmt::print("{} locale is missing.\n", loc_name);
|
||||
return;
|
||||
}
|
||||
std::ostringstream os;
|
||||
auto str = [&] {
|
||||
auto s = os.str();
|
||||
os.str("");
|
||||
return s;
|
||||
};
|
||||
os.imbue(loc);
|
||||
auto time = std::tm();
|
||||
time.tm_hour = 14;
|
||||
os << std::put_time(&time, "%OH");
|
||||
EXPECT_EQ(str(), fmt::format(loc, "{:%OH}", std::chrono::hours(14)));
|
||||
os << std::put_time(&time, "%OI");
|
||||
EXPECT_EQ(str(), fmt::format(loc, "{:%OI}", std::chrono::hours(14)));
|
||||
time.tm_minute = 42;
|
||||
os << std::put_time(&time, "%OM");
|
||||
EXPECT_EQ(str(), fmt::format(loc, "{:%OM}", std::chrono::minutes(42)));
|
||||
EXPECT_TIME("%OH", tm_hour, 14, hours);
|
||||
EXPECT_TIME("%OI", tm_hour, 14, hours);
|
||||
EXPECT_TIME("%OM", tm_min, 42, minutes);
|
||||
EXPECT_TIME("%OS", tm_min, 42, seconds);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user