1 // Formatting library for C++ - time formatting tests
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
6 // For the license information refer to format.h.
8 #include "fmt/chrono.h"
10 #include "gtest-extra.h" // EXPECT_THROW_MSG
11 #include "util.h" // get_locale
15 using testing::Contains
;
17 auto make_tm() -> std::tm
{
18 auto time
= std::tm();
23 auto make_hour(int h
) -> std::tm
{
24 auto time
= make_tm();
29 auto make_minute(int m
) -> std::tm
{
30 auto time
= make_tm();
35 auto make_second(int s
) -> std::tm
{
36 auto time
= make_tm();
41 TEST(chrono_test
, format_tm
) {
49 EXPECT_EQ(fmt::format("The date is {:%Y-%m-%d %H:%M:%S}.", tm
),
50 "The date is 2016-04-25 11:22:33.");
53 TEST(chrono_test
, grow_buffer
) {
54 auto s
= std::string("{:");
55 for (int i
= 0; i
< 30; ++i
) s
+= "%c";
57 auto t
= std::time(nullptr);
58 fmt::format(fmt::runtime(s
), *std::localtime(&t
));
61 TEST(chrono_test
, format_to_empty_container
) {
62 auto time
= std::tm();
64 auto s
= std::string();
65 fmt::format_to(std::back_inserter(s
), "{:%S}", time
);
69 TEST(chrono_test
, empty_result
) { EXPECT_EQ(fmt::format("{}", std::tm()), ""); }
71 auto equal(const std::tm
& lhs
, const std::tm
& rhs
) -> bool {
72 return lhs
.tm_sec
== rhs
.tm_sec
&& lhs
.tm_min
== rhs
.tm_min
&&
73 lhs
.tm_hour
== rhs
.tm_hour
&& lhs
.tm_mday
== rhs
.tm_mday
&&
74 lhs
.tm_mon
== rhs
.tm_mon
&& lhs
.tm_year
== rhs
.tm_year
&&
75 lhs
.tm_wday
== rhs
.tm_wday
&& lhs
.tm_yday
== rhs
.tm_yday
&&
76 lhs
.tm_isdst
== rhs
.tm_isdst
;
79 TEST(chrono_test
, localtime
) {
80 auto t
= std::time(nullptr);
81 auto tm
= *std::localtime(&t
);
82 EXPECT_TRUE(equal(tm
, fmt::localtime(t
)));
85 TEST(chrono_test
, gmtime
) {
86 auto t
= std::time(nullptr);
87 auto tm
= *std::gmtime(&t
);
88 EXPECT_TRUE(equal(tm
, fmt::gmtime(t
)));
91 template <typename TimePoint
> auto strftime(TimePoint tp
) -> std::string
{
92 auto t
= std::chrono::system_clock::to_time_t(tp
);
93 auto tm
= *std::localtime(&t
);
94 char output
[256] = {};
95 std::strftime(output
, sizeof(output
), "%Y-%m-%d %H:%M:%S", &tm
);
99 TEST(chrono_test
, time_point
) {
100 auto t1
= std::chrono::system_clock::now();
101 EXPECT_EQ(strftime(t1
), fmt::format("{:%Y-%m-%d %H:%M:%S}", t1
));
102 EXPECT_EQ(strftime(t1
), fmt::format("{}", t1
));
104 std::chrono::time_point
<std::chrono::system_clock
, std::chrono::seconds
>;
105 auto t2
= time_point(std::chrono::seconds(42));
106 EXPECT_EQ(strftime(t2
), fmt::format("{:%Y-%m-%d %H:%M:%S}", t2
));
109 #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
111 TEST(chrono_test
, format_default
) {
112 EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42)));
114 fmt::format("{}", std::chrono::duration
<int, std::atto
>(42)));
116 fmt::format("{}", std::chrono::duration
<int, std::femto
>(42)));
118 fmt::format("{}", std::chrono::duration
<int, std::pico
>(42)));
119 EXPECT_EQ("42ns", fmt::format("{}", std::chrono::nanoseconds(42)));
120 EXPECT_EQ("42µs", fmt::format("{}", std::chrono::microseconds(42)));
121 EXPECT_EQ("42ms", fmt::format("{}", std::chrono::milliseconds(42)));
123 fmt::format("{}", std::chrono::duration
<int, std::centi
>(42)));
125 fmt::format("{}", std::chrono::duration
<int, std::deci
>(42)));
126 EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42)));
128 fmt::format("{}", std::chrono::duration
<int, std::deca
>(42)));
130 fmt::format("{}", std::chrono::duration
<int, std::hecto
>(42)));
132 fmt::format("{}", std::chrono::duration
<int, std::kilo
>(42)));
134 fmt::format("{}", std::chrono::duration
<int, std::mega
>(42)));
136 fmt::format("{}", std::chrono::duration
<int, std::giga
>(42)));
138 fmt::format("{}", std::chrono::duration
<int, std::tera
>(42)));
140 fmt::format("{}", std::chrono::duration
<int, std::peta
>(42)));
142 fmt::format("{}", std::chrono::duration
<int, std::exa
>(42)));
143 EXPECT_EQ("42m", fmt::format("{}", std::chrono::minutes(42)));
144 EXPECT_EQ("42h", fmt::format("{}", std::chrono::hours(42)));
147 fmt::format("{}", std::chrono::duration
<int, std::ratio
<15, 1>>(42)));
150 fmt::format("{}", std::chrono::duration
<int, std::ratio
<15, 4>>(42)));
153 TEST(chrono_test
, align
) {
154 auto s
= std::chrono::seconds(42);
155 EXPECT_EQ("42s ", fmt::format("{:5}", s
));
156 EXPECT_EQ("42s ", fmt::format("{:{}}", s
, 5));
157 EXPECT_EQ(" 42s", fmt::format("{:>5}", s
));
158 EXPECT_EQ("**42s**", fmt::format("{:*^7}", s
));
159 EXPECT_EQ("03:25:45 ",
160 fmt::format("{:12%H:%M:%S}", std::chrono::seconds(12345)));
161 EXPECT_EQ(" 03:25:45",
162 fmt::format("{:>12%H:%M:%S}", std::chrono::seconds(12345)));
163 EXPECT_EQ("~~03:25:45~~",
164 fmt::format("{:~^12%H:%M:%S}", std::chrono::seconds(12345)));
165 EXPECT_EQ("03:25:45 ",
166 fmt::format("{:{}%H:%M:%S}", std::chrono::seconds(12345), 12));
169 TEST(chrono_test
, format_specs
) {
170 EXPECT_EQ("%", fmt::format("{:%%}", std::chrono::seconds(0)));
171 EXPECT_EQ("\n", fmt::format("{:%n}", std::chrono::seconds(0)));
172 EXPECT_EQ("\t", fmt::format("{:%t}", std::chrono::seconds(0)));
173 EXPECT_EQ("00", fmt::format("{:%S}", std::chrono::seconds(0)));
174 EXPECT_EQ("00", fmt::format("{:%S}", std::chrono::seconds(60)));
175 EXPECT_EQ("42", fmt::format("{:%S}", std::chrono::seconds(42)));
176 EXPECT_EQ("01.234", fmt::format("{:%S}", std::chrono::milliseconds(1234)));
177 EXPECT_EQ("00", fmt::format("{:%M}", std::chrono::minutes(0)));
178 EXPECT_EQ("00", fmt::format("{:%M}", std::chrono::minutes(60)));
179 EXPECT_EQ("42", fmt::format("{:%M}", std::chrono::minutes(42)));
180 EXPECT_EQ("01", fmt::format("{:%M}", std::chrono::seconds(61)));
181 EXPECT_EQ("00", fmt::format("{:%H}", std::chrono::hours(0)));
182 EXPECT_EQ("00", fmt::format("{:%H}", std::chrono::hours(24)));
183 EXPECT_EQ("14", fmt::format("{:%H}", std::chrono::hours(14)));
184 EXPECT_EQ("01", fmt::format("{:%H}", std::chrono::minutes(61)));
185 EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(0)));
186 EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(12)));
187 EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(24)));
188 EXPECT_EQ("04", fmt::format("{:%I}", std::chrono::hours(4)));
189 EXPECT_EQ("02", fmt::format("{:%I}", std::chrono::hours(14)));
190 EXPECT_EQ("03:25:45",
191 fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345)));
192 EXPECT_EQ("03:25", fmt::format("{:%R}", std::chrono::seconds(12345)));
193 EXPECT_EQ("03:25:45", fmt::format("{:%T}", std::chrono::seconds(12345)));
194 EXPECT_EQ("12345", fmt::format("{:%Q}", std::chrono::seconds(12345)));
195 EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(12345)));
198 TEST(chrono_test
, invalid_specs
) {
199 auto sec
= std::chrono::seconds(0);
200 EXPECT_THROW_MSG(fmt::format(runtime("{:%a}"), sec
), fmt::format_error
,
202 EXPECT_THROW_MSG(fmt::format(runtime("{:%A}"), sec
), fmt::format_error
,
204 EXPECT_THROW_MSG(fmt::format(runtime("{:%c}"), sec
), fmt::format_error
,
206 EXPECT_THROW_MSG(fmt::format(runtime("{:%x}"), sec
), fmt::format_error
,
208 EXPECT_THROW_MSG(fmt::format(runtime("{:%Ex}"), sec
), fmt::format_error
,
210 EXPECT_THROW_MSG(fmt::format(runtime("{:%X}"), sec
), fmt::format_error
,
212 EXPECT_THROW_MSG(fmt::format(runtime("{:%EX}"), sec
), fmt::format_error
,
214 EXPECT_THROW_MSG(fmt::format(runtime("{:%D}"), sec
), fmt::format_error
,
216 EXPECT_THROW_MSG(fmt::format(runtime("{:%F}"), sec
), fmt::format_error
,
218 EXPECT_THROW_MSG(fmt::format(runtime("{:%Ec}"), sec
), fmt::format_error
,
220 EXPECT_THROW_MSG(fmt::format(runtime("{:%w}"), sec
), fmt::format_error
,
222 EXPECT_THROW_MSG(fmt::format(runtime("{:%u}"), sec
), fmt::format_error
,
224 EXPECT_THROW_MSG(fmt::format(runtime("{:%b}"), sec
), fmt::format_error
,
226 EXPECT_THROW_MSG(fmt::format(runtime("{:%B}"), sec
), fmt::format_error
,
228 EXPECT_THROW_MSG(fmt::format(runtime("{:%z}"), sec
), fmt::format_error
,
230 EXPECT_THROW_MSG(fmt::format(runtime("{:%Z}"), sec
), fmt::format_error
,
232 EXPECT_THROW_MSG(fmt::format(runtime("{:%Eq}"), sec
), fmt::format_error
,
234 EXPECT_THROW_MSG(fmt::format(runtime("{:%Oq}"), sec
), fmt::format_error
,
238 auto format_tm(const std::tm
& time
, fmt::string_view spec
,
239 const std::locale
& loc
) -> std::string
{
240 auto& facet
= std::use_facet
<std::time_put
<char>>(loc
);
241 std::ostringstream os
;
243 facet
.put(os
, os
, ' ', &time
, spec
.begin(), spec
.end());
247 TEST(chrono_test
, locale
) {
248 auto loc
= get_locale("ja_JP.utf8");
249 if (loc
== std::locale::classic()) return;
250 # define EXPECT_TIME(spec, time, duration) \
252 auto jp_loc = std::locale("ja_JP.utf8"); \
253 EXPECT_EQ(format_tm(time, spec, jp_loc), \
254 fmt::format(jp_loc, "{:L" spec "}", duration)); \
256 EXPECT_TIME("%OH", make_hour(14), std::chrono::hours(14));
257 EXPECT_TIME("%OI", make_hour(14), std::chrono::hours(14));
258 EXPECT_TIME("%OM", make_minute(42), std::chrono::minutes(42));
259 EXPECT_TIME("%OS", make_second(42), std::chrono::seconds(42));
260 auto time
= make_tm();
264 auto sec
= std::chrono::seconds(12345);
265 EXPECT_TIME("%r", time
, sec
);
266 EXPECT_TIME("%p", time
, sec
);
269 using dms
= std::chrono::duration
<double, std::milli
>;
271 TEST(chrono_test
, format_default_fp
) {
272 typedef std::chrono::duration
<float> fs
;
273 EXPECT_EQ("1.234s", fmt::format("{}", fs(1.234)));
274 typedef std::chrono::duration
<float, std::milli
> fms
;
275 EXPECT_EQ("1.234ms", fmt::format("{}", fms(1.234)));
276 typedef std::chrono::duration
<double> ds
;
277 EXPECT_EQ("1.234s", fmt::format("{}", ds(1.234)));
278 EXPECT_EQ("1.234ms", fmt::format("{}", dms(1.234)));
281 TEST(chrono_test
, format_precision
) {
282 EXPECT_THROW_MSG(fmt::format(runtime("{:.2}"), std::chrono::seconds(42)),
284 "precision not allowed for this argument type");
285 EXPECT_EQ("1.2ms", fmt::format("{:.1}", dms(1.234)));
286 EXPECT_EQ("1.23ms", fmt::format("{:.{}}", dms(1.234), 2));
289 TEST(chrono_test
, format_full_specs
) {
290 EXPECT_EQ("1.2ms ", fmt::format("{:6.1}", dms(1.234)));
291 EXPECT_EQ(" 1.23ms", fmt::format("{:>8.{}}", dms(1.234), 2));
292 EXPECT_EQ(" 1.2ms ", fmt::format("{:^{}.{}}", dms(1.234), 7, 1));
293 EXPECT_EQ(" 1.23ms ", fmt::format("{0:^{2}.{1}}", dms(1.234), 2, 8));
294 EXPECT_EQ("=1.234ms=", fmt::format("{:=^{}.{}}", dms(1.234), 9, 3));
295 EXPECT_EQ("*1.2340ms*", fmt::format("{:*^10.4}", dms(1.234)));
298 TEST(chrono_test
, format_simple_q
) {
299 typedef std::chrono::duration
<float> fs
;
300 EXPECT_EQ("1.234 s", fmt::format("{:%Q %q}", fs(1.234)));
301 typedef std::chrono::duration
<float, std::milli
> fms
;
302 EXPECT_EQ("1.234 ms", fmt::format("{:%Q %q}", fms(1.234)));
303 typedef std::chrono::duration
<double> ds
;
304 EXPECT_EQ("1.234 s", fmt::format("{:%Q %q}", ds(1.234)));
305 EXPECT_EQ("1.234 ms", fmt::format("{:%Q %q}", dms(1.234)));
308 TEST(chrono_test
, format_precision_q
) {
309 EXPECT_THROW_MSG(fmt::format(runtime("{:.2%Q %q}"), std::chrono::seconds(42)),
311 "precision not allowed for this argument type");
312 EXPECT_EQ("1.2 ms", fmt::format("{:.1%Q %q}", dms(1.234)));
313 EXPECT_EQ("1.23 ms", fmt::format("{:.{}%Q %q}", dms(1.234), 2));
316 TEST(chrono_test
, format_full_specs_q
) {
317 EXPECT_EQ("1.2 ms ", fmt::format("{:7.1%Q %q}", dms(1.234)));
318 EXPECT_EQ(" 1.23 ms", fmt::format("{:>8.{}%Q %q}", dms(1.234), 2));
319 EXPECT_EQ(" 1.2 ms ", fmt::format("{:^{}.{}%Q %q}", dms(1.234), 8, 1));
320 EXPECT_EQ(" 1.23 ms ", fmt::format("{0:^{2}.{1}%Q %q}", dms(1.234), 2, 9));
321 EXPECT_EQ("=1.234 ms=", fmt::format("{:=^{}.{}%Q %q}", dms(1.234), 10, 3));
322 EXPECT_EQ("*1.2340 ms*", fmt::format("{:*^11.4%Q %q}", dms(1.234)));
325 TEST(chrono_test
, invalid_width_id
) {
326 EXPECT_THROW(fmt::format(runtime("{:{o}"), std::chrono::seconds(0)),
330 TEST(chrono_test
, invalid_colons
) {
331 EXPECT_THROW(fmt::format(runtime("{0}=:{0::"), std::chrono::seconds(0)),
335 TEST(chrono_test
, negative_durations
) {
336 EXPECT_EQ("-12345", fmt::format("{:%Q}", std::chrono::seconds(-12345)));
337 EXPECT_EQ("-03:25:45",
338 fmt::format("{:%H:%M:%S}", std::chrono::seconds(-12345)));
340 fmt::format("{:%M:%S}", std::chrono::duration
<double>(-1)));
341 EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(-12345)));
344 std::chrono::duration
<signed char, std::milli
>{-127}));
345 auto min
= std::numeric_limits
<int>::min();
346 EXPECT_EQ(fmt::format("{}", min
),
347 fmt::format("{:%Q}", std::chrono::duration
<int>(min
)));
350 TEST(chrono_test
, special_durations
) {
353 fmt::format("{:%S}", std::chrono::duration
<double>(1e20
)).substr(0, 3));
354 auto nan
= std::numeric_limits
<double>::quiet_NaN();
356 "nan nan nan nan nan:nan nan",
357 fmt::format("{:%I %H %M %S %R %r}", std::chrono::duration
<double>(nan
)));
359 std::chrono::duration
<float, std::atto
>(1.79400457e+31f
));
360 EXPECT_EQ(fmt::format("{}", std::chrono::duration
<float, std::exa
>(1)),
362 EXPECT_EQ(fmt::format("{}", std::chrono::duration
<float, std::atto
>(1)),
364 EXPECT_EQ(fmt::format("{:%R}", std::chrono::duration
<char, std::mega
>{2}),
366 EXPECT_EQ(fmt::format("{:%T}", std::chrono::duration
<char, std::mega
>{2}),
370 TEST(chrono_test
, unsigned_duration
) {
371 EXPECT_EQ("42s", fmt::format("{}", std::chrono::duration
<unsigned>(42)));
374 TEST(chrono_test
, weekday
) {
375 auto loc
= get_locale("ru_RU.UTF-8");
376 std::locale::global(loc
);
377 auto mon
= fmt::weekday(1);
378 EXPECT_EQ(fmt::format("{}", mon
), "Mon");
379 if (loc
!= std::locale::classic()) {
380 EXPECT_THAT((std::vector
<std::string
>{"пн", "Пн", "пнд", "Пнд"}),
381 Contains(fmt::format(loc
, "{:L}", mon
)));
385 #endif // FMT_STATIC_THOUSANDS_SEPARATOR