chrono-test.cc
1 // Formatting library for C++ - time formatting tests 2 // 3 // Copyright (c) 2012 - present, Victor Zverovich 4 // All rights reserved. 5 // 6 // For the license information refer to format.h. 7 8 #include "fmt/chrono.h" 9 10 #include <algorithm> 11 #include <ctime> 12 #include <vector> 13 14 #include "gtest-extra.h" // EXPECT_THROW_MSG 15 #include "util.h" // get_locale 16 17 using fmt::runtime; 18 using testing::Contains; 19 20 #if defined(__MINGW32__) && !defined(_UCRT) 21 // Only C89 conversion specifiers when using MSVCRT instead of UCRT 22 # define FMT_HAS_C99_STRFTIME 0 23 #else 24 # define FMT_HAS_C99_STRFTIME 1 25 #endif 26 27 auto make_tm() -> std::tm { 28 auto time = std::tm(); 29 time.tm_mday = 1; 30 return time; 31 } 32 33 auto make_hour(int h) -> std::tm { 34 auto time = make_tm(); 35 time.tm_hour = h; 36 return time; 37 } 38 39 auto make_minute(int m) -> std::tm { 40 auto time = make_tm(); 41 time.tm_min = m; 42 return time; 43 } 44 45 auto make_second(int s) -> std::tm { 46 auto time = make_tm(); 47 time.tm_sec = s; 48 return time; 49 } 50 51 std::string system_strftime(const std::string& format, const std::tm* timeptr, 52 std::locale* locptr = nullptr) { 53 auto loc = locptr ? *locptr : std::locale::classic(); 54 auto& facet = std::use_facet<std::time_put<char>>(loc); 55 std::ostringstream os; 56 os.imbue(loc); 57 facet.put(os, os, ' ', timeptr, format.c_str(), 58 format.c_str() + format.size()); 59 #ifdef _WIN32 60 // Workaround a bug in older versions of Universal CRT. 61 auto str = os.str(); 62 if (str == "-0000") str = "+0000"; 63 return str; 64 #else 65 return os.str(); 66 #endif 67 } 68 69 FMT_CONSTEXPR std::tm make_tm(int year, int mon, int mday, int hour, int min, 70 int sec) { 71 auto tm = std::tm(); 72 tm.tm_sec = sec; 73 tm.tm_min = min; 74 tm.tm_hour = hour; 75 tm.tm_mday = mday; 76 tm.tm_mon = mon - 1; 77 tm.tm_year = year - 1900; 78 return tm; 79 } 80 81 TEST(chrono_test, format_tm) { 82 auto tm = std::tm(); 83 tm.tm_year = 116; 84 tm.tm_mon = 3; 85 tm.tm_mday = 25; 86 tm.tm_hour = 11; 87 tm.tm_min = 22; 88 tm.tm_sec = 33; 89 EXPECT_EQ(fmt::format("The date is {:%Y-%m-%d %H:%M:%S}.", tm), 90 "The date is 2016-04-25 11:22:33."); 91 EXPECT_EQ(fmt::format("{:%Y}", tm), "2016"); 92 EXPECT_EQ(fmt::format("{:%C}", tm), "20"); 93 EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm)); 94 EXPECT_EQ(fmt::format("{:%e}", tm), "25"); 95 EXPECT_EQ(fmt::format("{:%D}", tm), "04/25/16"); 96 EXPECT_EQ(fmt::format("{:%F}", tm), "2016-04-25"); 97 EXPECT_EQ(fmt::format("{:%T}", tm), "11:22:33"); 98 99 // Short year 100 tm.tm_year = 999 - 1900; 101 tm.tm_mon = 0; // for %G 102 tm.tm_mday = 2; // for %G 103 tm.tm_wday = 3; // for %G 104 tm.tm_yday = 1; // for %G 105 EXPECT_EQ(fmt::format("{:%Y}", tm), "0999"); 106 EXPECT_EQ(fmt::format("{:%C%y}", tm), "0999"); 107 EXPECT_EQ(fmt::format("{:%G}", tm), "0999"); 108 109 tm.tm_year = 27 - 1900; 110 EXPECT_EQ(fmt::format("{:%Y}", tm), "0027"); 111 EXPECT_EQ(fmt::format("{:%C%y}", tm), "0027"); 112 113 // Overflow year 114 tm.tm_year = 2147483647; 115 EXPECT_EQ(fmt::format("{:%Y}", tm), "2147485547"); 116 117 tm.tm_year = -2147483648; 118 EXPECT_EQ(fmt::format("{:%Y}", tm), "-2147481748"); 119 120 // for week on the year 121 // https://www.cl.cam.ac.uk/~mgk25/iso-time.html 122 std::vector<std::tm> tm_list = { 123 make_tm(1975, 12, 29, 12, 14, 16), // W01 124 make_tm(1977, 1, 2, 12, 14, 16), // W53 125 make_tm(1999, 12, 27, 12, 14, 16), // W52 126 make_tm(1999, 12, 31, 12, 14, 16), // W52 127 make_tm(2000, 1, 1, 12, 14, 16), // W52 128 make_tm(2000, 1, 2, 12, 14, 16), // W52 129 make_tm(2000, 1, 3, 12, 14, 16) // W1 130 }; 131 132 #if !FMT_HAS_C99_STRFTIME 133 GTEST_SKIP() << "Skip the rest of this test because it relies on strftime() " 134 "conforming to C99, but on this platform, MINGW + MSVCRT, " 135 "the function conforms only to C89."; 136 #endif 137 138 const std::string iso_week_spec = "%Y-%m-%d: %G %g %V"; 139 for (auto ctm : tm_list) { 140 // Calculate tm_yday, tm_wday, etc. 141 std::time_t t = std::mktime(&ctm); 142 tm = *std::localtime(&t); 143 144 auto fmt_spec = fmt::format("{{:{}}}", iso_week_spec); 145 EXPECT_EQ(system_strftime(iso_week_spec, &tm), 146 fmt::format(fmt::runtime(fmt_spec), tm)); 147 } 148 149 // Every day from 1970-01-01 150 std::time_t time_now = std::time(nullptr); 151 for (std::time_t t = 6 * 3600; t < time_now; t += 86400) { 152 tm = *std::localtime(&t); 153 154 auto fmt_spec = fmt::format("{{:{}}}", iso_week_spec); 155 EXPECT_EQ(system_strftime(iso_week_spec, &tm), 156 fmt::format(fmt::runtime(fmt_spec), tm)); 157 } 158 } 159 160 // MSVC: 161 // minkernel\crts\ucrt\src\appcrt\time\wcsftime.cpp(971) : Assertion failed: 162 // timeptr->tm_year >= -1900 && timeptr->tm_year <= 8099 163 #ifndef _WIN32 164 TEST(chrono_test, format_tm_future) { 165 auto tm = std::tm(); 166 tm.tm_year = 10445; // 10000+ years 167 tm.tm_mon = 3; 168 tm.tm_mday = 25; 169 tm.tm_hour = 11; 170 tm.tm_min = 22; 171 tm.tm_sec = 33; 172 EXPECT_EQ(fmt::format("The date is {:%Y-%m-%d %H:%M:%S}.", tm), 173 "The date is 12345-04-25 11:22:33."); 174 EXPECT_EQ(fmt::format("{:%Y}", tm), "12345"); 175 EXPECT_EQ(fmt::format("{:%C}", tm), "123"); 176 EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm)); 177 EXPECT_EQ(fmt::format("{:%D}", tm), "04/25/45"); 178 EXPECT_EQ(fmt::format("{:%F}", tm), "12345-04-25"); 179 EXPECT_EQ(fmt::format("{:%T}", tm), "11:22:33"); 180 } 181 182 TEST(chrono_test, format_tm_past) { 183 auto tm = std::tm(); 184 tm.tm_year = -2001; 185 tm.tm_mon = 3; 186 tm.tm_mday = 25; 187 tm.tm_hour = 11; 188 tm.tm_min = 22; 189 tm.tm_sec = 33; 190 EXPECT_EQ(fmt::format("The date is {:%Y-%m-%d %H:%M:%S}.", tm), 191 "The date is -101-04-25 11:22:33."); 192 EXPECT_EQ(fmt::format("{:%Y}", tm), "-101"); 193 194 // macOS %C - "-1" 195 // Linux %C - "-2" 196 // fmt %C - "-1" 197 EXPECT_EQ(fmt::format("{:%C}", tm), "-1"); 198 EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm)); 199 200 // macOS %D - "04/25/01" (%y) 201 // Linux %D - "04/25/99" (%y) 202 // fmt %D - "04/25/01" (%y) 203 EXPECT_EQ(fmt::format("{:%D}", tm), "04/25/01"); 204 205 EXPECT_EQ(fmt::format("{:%F}", tm), "-101-04-25"); 206 EXPECT_EQ(fmt::format("{:%T}", tm), "11:22:33"); 207 208 tm.tm_year = -1901; // -1 209 EXPECT_EQ(fmt::format("{:%Y}", tm), "-001"); 210 EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm)); 211 212 tm.tm_year = -1911; // -11 213 EXPECT_EQ(fmt::format("{:%Y}", tm), "-011"); 214 EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm)); 215 } 216 #endif 217 218 TEST(chrono_test, grow_buffer) { 219 auto s = std::string("{:"); 220 for (int i = 0; i < 30; ++i) s += "%c"; 221 s += "}\n"; 222 auto t = std::time(nullptr); 223 (void)fmt::format(fmt::runtime(s), *std::localtime(&t)); 224 } 225 226 TEST(chrono_test, format_to_empty_container) { 227 auto time = std::tm(); 228 time.tm_sec = 42; 229 auto s = std::string(); 230 fmt::format_to(std::back_inserter(s), "{:%S}", time); 231 EXPECT_EQ(s, "42"); 232 } 233 234 TEST(chrono_test, empty_result) { EXPECT_EQ(fmt::format("{}", std::tm()), ""); } 235 236 auto equal(const std::tm& lhs, const std::tm& rhs) -> bool { 237 return lhs.tm_sec == rhs.tm_sec && lhs.tm_min == rhs.tm_min && 238 lhs.tm_hour == rhs.tm_hour && lhs.tm_mday == rhs.tm_mday && 239 lhs.tm_mon == rhs.tm_mon && lhs.tm_year == rhs.tm_year && 240 lhs.tm_wday == rhs.tm_wday && lhs.tm_yday == rhs.tm_yday && 241 lhs.tm_isdst == rhs.tm_isdst; 242 } 243 244 TEST(chrono_test, gmtime) { 245 auto t = std::time(nullptr); 246 auto tm = *std::gmtime(&t); 247 EXPECT_TRUE(equal(tm, fmt::gmtime(t))); 248 } 249 250 template <typename TimePoint> 251 auto strftime_full_utc(TimePoint tp) -> std::string { 252 auto t = std::chrono::system_clock::to_time_t(tp); 253 auto tm = *std::gmtime(&t); 254 return system_strftime("%Y-%m-%d %H:%M:%S", &tm); 255 } 256 257 TEST(chrono_test, system_clock_time_point) { 258 auto t1 = std::chrono::time_point_cast<std::chrono::seconds>( 259 std::chrono::system_clock::now()); 260 EXPECT_EQ(strftime_full_utc(t1), fmt::format("{:%Y-%m-%d %H:%M:%S}", t1)); 261 EXPECT_EQ(strftime_full_utc(t1), fmt::format("{}", t1)); 262 EXPECT_EQ(strftime_full_utc(t1), fmt::format("{:}", t1)); 263 using time_point = 264 std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>; 265 auto t2 = time_point(std::chrono::seconds(42)); 266 EXPECT_EQ(strftime_full_utc(t2), fmt::format("{:%Y-%m-%d %H:%M:%S}", t2)); 267 268 std::vector<std::string> spec_list = { 269 "%%", "%n", "%t", "%Y", "%EY", "%y", "%Oy", "%Ey", "%C", 270 "%EC", "%G", "%g", "%b", "%h", "%B", "%m", "%Om", "%U", 271 "%OU", "%W", "%OW", "%V", "%OV", "%j", "%d", "%Od", "%e", 272 "%Oe", "%a", "%A", "%w", "%Ow", "%u", "%Ou", "%H", "%OH", 273 "%I", "%OI", "%M", "%OM", "%S", "%OS", "%x", "%Ex", "%X", 274 "%EX", "%D", "%F", "%R", "%T", "%p"}; 275 #ifndef _WIN32 276 // Disabled on Windows because these formats are not consistent among 277 // platforms. 278 spec_list.insert(spec_list.end(), {"%c", "%Ec", "%r"}); 279 #elif !FMT_HAS_C99_STRFTIME 280 // Only C89 conversion specifiers when using MSVCRT instead of UCRT 281 spec_list = {"%%", "%Y", "%y", "%b", "%B", "%m", "%U", "%W", "%j", "%d", 282 "%a", "%A", "%w", "%H", "%I", "%M", "%S", "%x", "%X", "%p"}; 283 #endif 284 spec_list.push_back("%Y-%m-%d %H:%M:%S"); 285 286 for (const auto& spec : spec_list) { 287 auto t = std::chrono::system_clock::to_time_t(t1); 288 auto tm = *std::gmtime(&t); 289 290 auto sys_output = system_strftime(spec, &tm); 291 292 auto fmt_spec = fmt::format("{{:{}}}", spec); 293 EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), t1)); 294 EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm)); 295 } 296 297 // Timezone formatters tests makes sense for localtime. 298 #if FMT_HAS_C99_STRFTIME 299 spec_list = {"%z", "%Z"}; 300 #else 301 spec_list = {"%Z"}; 302 #endif 303 for (const auto& spec : spec_list) { 304 auto t = std::chrono::system_clock::to_time_t(t1); 305 auto tm = *std::localtime(&t); 306 307 auto sys_output = system_strftime(spec, &tm); 308 309 auto fmt_spec = fmt::format("{{:{}}}", spec); 310 EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm)); 311 312 if (spec == "%z") { 313 sys_output.insert(sys_output.end() - 2, 1, ':'); 314 EXPECT_EQ(sys_output, fmt::format("{:%Ez}", tm)); 315 EXPECT_EQ(sys_output, fmt::format("{:%Oz}", tm)); 316 } 317 } 318 319 // Separate tests for UTC, since std::time_put can use local time and ignoring 320 // the timezone in std::tm (if it presents on platform). 321 if (fmt::detail::has_member_data_tm_zone<std::tm>::value) { 322 auto t = std::chrono::system_clock::to_time_t(t1); 323 auto tm = *std::gmtime(&t); 324 325 std::vector<std::string> tz_names = {"GMT", "UTC"}; 326 EXPECT_THAT(tz_names, Contains(fmt::format("{:%Z}", t1))); 327 EXPECT_THAT(tz_names, Contains(fmt::format("{:%Z}", tm))); 328 } 329 330 if (fmt::detail::has_member_data_tm_gmtoff<std::tm>::value) { 331 auto t = std::chrono::system_clock::to_time_t(t1); 332 auto tm = *std::gmtime(&t); 333 334 EXPECT_EQ("+0000", fmt::format("{:%z}", t1)); 335 EXPECT_EQ("+0000", fmt::format("{:%z}", tm)); 336 337 EXPECT_EQ("+00:00", fmt::format("{:%Ez}", t1)); 338 EXPECT_EQ("+00:00", fmt::format("{:%Ez}", tm)); 339 340 EXPECT_EQ("+00:00", fmt::format("{:%Oz}", t1)); 341 EXPECT_EQ("+00:00", fmt::format("{:%Oz}", tm)); 342 } 343 } 344 345 #if FMT_USE_LOCAL_TIME 346 347 TEST(chrono_test, localtime) { 348 auto t = std::time(nullptr); 349 auto tm = *std::localtime(&t); 350 EXPECT_TRUE(equal(tm, fmt::localtime(t))); 351 } 352 353 template <typename Duration> 354 auto strftime_full_local(std::chrono::local_time<Duration> tp) -> std::string { 355 auto t = std::chrono::system_clock::to_time_t( 356 std::chrono::current_zone()->to_sys(tp)); 357 auto tm = *std::localtime(&t); 358 return system_strftime("%Y-%m-%d %H:%M:%S", &tm); 359 } 360 361 TEST(chrono_test, local_system_clock_time_point) { 362 # ifdef _WIN32 363 return; // Not supported on Windows. 364 # endif 365 auto t1 = std::chrono::time_point_cast<std::chrono::seconds>( 366 std::chrono::current_zone()->to_local(std::chrono::system_clock::now())); 367 EXPECT_EQ(strftime_full_local(t1), fmt::format("{:%Y-%m-%d %H:%M:%S}", t1)); 368 EXPECT_EQ(strftime_full_local(t1), fmt::format("{}", t1)); 369 EXPECT_EQ(strftime_full_local(t1), fmt::format("{:}", t1)); 370 using time_point = std::chrono::local_time<std::chrono::seconds>; 371 auto t2 = time_point(std::chrono::seconds(86400 + 42)); 372 EXPECT_EQ(strftime_full_local(t2), fmt::format("{:%Y-%m-%d %H:%M:%S}", t2)); 373 374 std::vector<std::string> spec_list = { 375 "%%", "%n", "%t", "%Y", "%EY", "%y", "%Oy", "%Ey", "%C", 376 "%EC", "%G", "%g", "%b", "%h", "%B", "%m", "%Om", "%U", 377 "%OU", "%W", "%OW", "%V", "%OV", "%j", "%d", "%Od", "%e", 378 "%Oe", "%a", "%A", "%w", "%Ow", "%u", "%Ou", "%H", "%OH", 379 "%I", "%OI", "%M", "%OM", "%S", "%OS", "%x", "%Ex", "%X", 380 "%EX", "%D", "%F", "%R", "%T", "%p", "%z", "%Z"}; 381 # ifndef _WIN32 382 // Disabled on Windows because these formats are not consistent among 383 // platforms. 384 spec_list.insert(spec_list.end(), {"%c", "%Ec", "%r"}); 385 # elif !FMT_HAS_C99_STRFTIME 386 // Only C89 conversion specifiers when using MSVCRT instead of UCRT 387 spec_list = {"%%", "%Y", "%y", "%b", "%B", "%m", "%U", "%W", "%j", "%d", "%a", 388 "%A", "%w", "%H", "%I", "%M", "%S", "%x", "%X", "%p", "%Z"}; 389 # endif 390 spec_list.push_back("%Y-%m-%d %H:%M:%S"); 391 392 for (const auto& spec : spec_list) { 393 auto t = std::chrono::system_clock::to_time_t( 394 std::chrono::current_zone()->to_sys(t1)); 395 auto tm = *std::localtime(&t); 396 397 auto sys_output = system_strftime(spec, &tm); 398 399 auto fmt_spec = fmt::format("{{:{}}}", spec); 400 EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), t1)); 401 EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm)); 402 } 403 404 if (std::find(spec_list.cbegin(), spec_list.cend(), "%z") != 405 spec_list.cend()) { 406 auto t = std::chrono::system_clock::to_time_t( 407 std::chrono::current_zone()->to_sys(t1)); 408 auto tm = *std::localtime(&t); 409 410 auto sys_output = system_strftime("%z", &tm); 411 sys_output.insert(sys_output.end() - 2, 1, ':'); 412 413 EXPECT_EQ(sys_output, fmt::format("{:%Ez}", t1)); 414 EXPECT_EQ(sys_output, fmt::format("{:%Ez}", tm)); 415 416 EXPECT_EQ(sys_output, fmt::format("{:%Oz}", t1)); 417 EXPECT_EQ(sys_output, fmt::format("{:%Oz}", tm)); 418 } 419 } 420 421 #endif // FMT_USE_LOCAL_TIME 422 423 #ifndef FMT_STATIC_THOUSANDS_SEPARATOR 424 425 TEST(chrono_test, format_default) { 426 EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42))); 427 EXPECT_EQ("42as", 428 fmt::format("{}", std::chrono::duration<int, std::atto>(42))); 429 EXPECT_EQ("42fs", 430 fmt::format("{}", std::chrono::duration<int, std::femto>(42))); 431 EXPECT_EQ("42ps", 432 fmt::format("{}", std::chrono::duration<int, std::pico>(42))); 433 EXPECT_EQ("42ns", fmt::format("{}", std::chrono::nanoseconds(42))); 434 EXPECT_EQ("42µs", fmt::format("{}", std::chrono::microseconds(42))); 435 EXPECT_EQ("42ms", fmt::format("{}", std::chrono::milliseconds(42))); 436 EXPECT_EQ("42cs", 437 fmt::format("{}", std::chrono::duration<int, std::centi>(42))); 438 EXPECT_EQ("42ds", 439 fmt::format("{}", std::chrono::duration<int, std::deci>(42))); 440 EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42))); 441 EXPECT_EQ("42das", 442 fmt::format("{}", std::chrono::duration<int, std::deca>(42))); 443 EXPECT_EQ("42hs", 444 fmt::format("{}", std::chrono::duration<int, std::hecto>(42))); 445 EXPECT_EQ("42ks", 446 fmt::format("{}", std::chrono::duration<int, std::kilo>(42))); 447 EXPECT_EQ("42Ms", 448 fmt::format("{}", std::chrono::duration<int, std::mega>(42))); 449 EXPECT_EQ("42Gs", 450 fmt::format("{}", std::chrono::duration<int, std::giga>(42))); 451 EXPECT_EQ("42Ts", 452 fmt::format("{}", std::chrono::duration<int, std::tera>(42))); 453 EXPECT_EQ("42Ps", 454 fmt::format("{}", std::chrono::duration<int, std::peta>(42))); 455 EXPECT_EQ("42Es", 456 fmt::format("{}", std::chrono::duration<int, std::exa>(42))); 457 EXPECT_EQ("42m", fmt::format("{}", std::chrono::minutes(42))); 458 EXPECT_EQ("42h", fmt::format("{}", std::chrono::hours(42))); 459 EXPECT_EQ( 460 "42[15]s", 461 fmt::format("{}", std::chrono::duration<int, std::ratio<15, 1>>(42))); 462 EXPECT_EQ( 463 "42[15/4]s", 464 fmt::format("{}", std::chrono::duration<int, std::ratio<15, 4>>(42))); 465 } 466 467 TEST(chrono_test, duration_align) { 468 auto s = std::chrono::seconds(42); 469 EXPECT_EQ("42s ", fmt::format("{:5}", s)); 470 EXPECT_EQ("42s ", fmt::format("{:{}}", s, 5)); 471 EXPECT_EQ(" 42s", fmt::format("{:>5}", s)); 472 EXPECT_EQ("**42s**", fmt::format("{:*^7}", s)); 473 EXPECT_EQ("03:25:45 ", 474 fmt::format("{:12%H:%M:%S}", std::chrono::seconds(12345))); 475 EXPECT_EQ(" 03:25:45", 476 fmt::format("{:>12%H:%M:%S}", std::chrono::seconds(12345))); 477 EXPECT_EQ("~~03:25:45~~", 478 fmt::format("{:~^12%H:%M:%S}", std::chrono::seconds(12345))); 479 EXPECT_EQ("03:25:45 ", 480 fmt::format("{:{}%H:%M:%S}", std::chrono::seconds(12345), 12)); 481 } 482 483 TEST(chrono_test, tm_align) { 484 auto t = make_tm(1975, 12, 29, 12, 14, 16); 485 EXPECT_EQ("1975-12-29 12:14:16", fmt::format("{:%F %T}", t)); 486 EXPECT_EQ("1975-12-29 12:14:16 ", fmt::format("{:30%F %T}", t)); 487 EXPECT_EQ("1975-12-29 12:14:16 ", fmt::format("{:{}%F %T}", t, 30)); 488 EXPECT_EQ("1975-12-29 12:14:16 ", fmt::format("{:<30%F %T}", t)); 489 EXPECT_EQ(" 1975-12-29 12:14:16 ", fmt::format("{:^30%F %T}", t)); 490 EXPECT_EQ(" 1975-12-29 12:14:16", fmt::format("{:>30%F %T}", t)); 491 492 EXPECT_EQ("1975-12-29 12:14:16***********", fmt::format("{:*<30%F %T}", t)); 493 EXPECT_EQ("*****1975-12-29 12:14:16******", fmt::format("{:*^30%F %T}", t)); 494 EXPECT_EQ("***********1975-12-29 12:14:16", fmt::format("{:*>30%F %T}", t)); 495 } 496 497 TEST(chrono_test, tp_align) { 498 auto tp = std::chrono::time_point_cast<std::chrono::microseconds>( 499 std::chrono::system_clock::from_time_t(0)); 500 EXPECT_EQ("00:00.000000", fmt::format("{:%M:%S}", tp)); 501 EXPECT_EQ("00:00.000000 ", fmt::format("{:15%M:%S}", tp)); 502 EXPECT_EQ("00:00.000000 ", fmt::format("{:{}%M:%S}", tp, 15)); 503 EXPECT_EQ("00:00.000000 ", fmt::format("{:<15%M:%S}", tp)); 504 EXPECT_EQ(" 00:00.000000 ", fmt::format("{:^15%M:%S}", tp)); 505 EXPECT_EQ(" 00:00.000000", fmt::format("{:>15%M:%S}", tp)); 506 507 EXPECT_EQ("00:00.000000***", fmt::format("{:*<15%M:%S}", tp)); 508 EXPECT_EQ("*00:00.000000**", fmt::format("{:*^15%M:%S}", tp)); 509 EXPECT_EQ("***00:00.000000", fmt::format("{:*>15%M:%S}", tp)); 510 } 511 512 TEST(chrono_test, format_specs) { 513 EXPECT_EQ("%", fmt::format("{:%%}", std::chrono::seconds(0))); 514 EXPECT_EQ("\n", fmt::format("{:%n}", std::chrono::seconds(0))); 515 EXPECT_EQ("\t", fmt::format("{:%t}", std::chrono::seconds(0))); 516 EXPECT_EQ("00", fmt::format("{:%S}", std::chrono::seconds(0))); 517 EXPECT_EQ("00", fmt::format("{:%S}", std::chrono::seconds(60))); 518 EXPECT_EQ("42", fmt::format("{:%S}", std::chrono::seconds(42))); 519 EXPECT_EQ("01.234", fmt::format("{:%S}", std::chrono::milliseconds(1234))); 520 EXPECT_EQ("00", fmt::format("{:%M}", std::chrono::minutes(0))); 521 EXPECT_EQ("00", fmt::format("{:%M}", std::chrono::minutes(60))); 522 EXPECT_EQ("42", fmt::format("{:%M}", std::chrono::minutes(42))); 523 EXPECT_EQ("01", fmt::format("{:%M}", std::chrono::seconds(61))); 524 EXPECT_EQ("00", fmt::format("{:%H}", std::chrono::hours(0))); 525 EXPECT_EQ("00", fmt::format("{:%H}", std::chrono::hours(24))); 526 EXPECT_EQ("14", fmt::format("{:%H}", std::chrono::hours(14))); 527 EXPECT_EQ("01", fmt::format("{:%H}", std::chrono::minutes(61))); 528 EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(0))); 529 EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(12))); 530 EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(24))); 531 EXPECT_EQ("04", fmt::format("{:%I}", std::chrono::hours(4))); 532 EXPECT_EQ("02", fmt::format("{:%I}", std::chrono::hours(14))); 533 EXPECT_EQ("03:25:45", 534 fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345))); 535 EXPECT_EQ("03:25", fmt::format("{:%R}", std::chrono::seconds(12345))); 536 EXPECT_EQ("03:25:45", fmt::format("{:%T}", std::chrono::seconds(12345))); 537 EXPECT_EQ("12345", fmt::format("{:%Q}", std::chrono::seconds(12345))); 538 EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(12345))); 539 } 540 541 TEST(chrono_test, invalid_specs) { 542 auto sec = std::chrono::seconds(0); 543 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%a}"), sec), fmt::format_error, 544 "no date"); 545 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%A}"), sec), fmt::format_error, 546 "no date"); 547 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%c}"), sec), fmt::format_error, 548 "no date"); 549 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%x}"), sec), fmt::format_error, 550 "no date"); 551 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Ex}"), sec), fmt::format_error, 552 "no date"); 553 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%X}"), sec), fmt::format_error, 554 "no date"); 555 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%EX}"), sec), fmt::format_error, 556 "no date"); 557 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%D}"), sec), fmt::format_error, 558 "no date"); 559 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%F}"), sec), fmt::format_error, 560 "no date"); 561 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Ec}"), sec), fmt::format_error, 562 "no date"); 563 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%w}"), sec), fmt::format_error, 564 "no date"); 565 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%u}"), sec), fmt::format_error, 566 "no date"); 567 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%b}"), sec), fmt::format_error, 568 "no date"); 569 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%B}"), sec), fmt::format_error, 570 "no date"); 571 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%z}"), sec), fmt::format_error, 572 "no date"); 573 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Z}"), sec), fmt::format_error, 574 "no date"); 575 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Eq}"), sec), fmt::format_error, 576 "invalid format"); 577 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Oq}"), sec), fmt::format_error, 578 "invalid format"); 579 EXPECT_THROW_MSG((void)fmt::format(runtime("{:abc}"), sec), fmt::format_error, 580 "invalid format"); 581 EXPECT_THROW_MSG((void)fmt::format(runtime("{:.2f}"), sec), fmt::format_error, 582 "invalid format"); 583 } 584 585 auto format_tm(const std::tm& time, fmt::string_view spec, 586 const std::locale& loc) -> std::string { 587 auto& facet = std::use_facet<std::time_put<char>>(loc); 588 std::ostringstream os; 589 os.imbue(loc); 590 facet.put(os, os, ' ', &time, spec.begin(), spec.end()); 591 return os.str(); 592 } 593 594 TEST(chrono_test, locale) { 595 auto loc = get_locale("ja_JP.utf8"); 596 if (loc == std::locale::classic()) return; 597 # define EXPECT_TIME(spec, time, duration) \ 598 { \ 599 auto jp_loc = std::locale("ja_JP.utf8"); \ 600 EXPECT_EQ(format_tm(time, spec, jp_loc), \ 601 fmt::format(jp_loc, "{:L" spec "}", duration)); \ 602 } 603 EXPECT_TIME("%OH", make_hour(14), std::chrono::hours(14)); 604 EXPECT_TIME("%OI", make_hour(14), std::chrono::hours(14)); 605 EXPECT_TIME("%OM", make_minute(42), std::chrono::minutes(42)); 606 EXPECT_TIME("%OS", make_second(42), std::chrono::seconds(42)); 607 auto time = make_tm(); 608 time.tm_hour = 3; 609 time.tm_min = 25; 610 time.tm_sec = 45; 611 auto sec = std::chrono::seconds(12345); 612 EXPECT_TIME("%r", time, sec); 613 EXPECT_TIME("%p", time, sec); 614 } 615 616 using dms = std::chrono::duration<double, std::milli>; 617 618 TEST(chrono_test, format_default_fp) { 619 typedef std::chrono::duration<float> fs; 620 EXPECT_EQ("1.234s", fmt::format("{}", fs(1.234))); 621 typedef std::chrono::duration<float, std::milli> fms; 622 EXPECT_EQ("1.234ms", fmt::format("{}", fms(1.234))); 623 typedef std::chrono::duration<double> ds; 624 EXPECT_EQ("1.234s", fmt::format("{}", ds(1.234))); 625 EXPECT_EQ("1.234ms", fmt::format("{}", dms(1.234))); 626 } 627 628 TEST(chrono_test, format_precision) { 629 EXPECT_THROW_MSG( 630 (void)fmt::format(runtime("{:.2%Q}"), std::chrono::seconds(42)), 631 fmt::format_error, "precision not allowed for this argument type"); 632 EXPECT_EQ("1ms", fmt::format("{:.0}", dms(1.234))); 633 EXPECT_EQ("1.2ms", fmt::format("{:.1}", dms(1.234))); 634 EXPECT_EQ("1.23ms", fmt::format("{:.{}}", dms(1.234), 2)); 635 636 EXPECT_EQ("13ms", fmt::format("{:.0}", dms(12.56))); 637 EXPECT_EQ("12.6ms", fmt::format("{:.1}", dms(12.56))); 638 EXPECT_EQ("12.56ms", fmt::format("{:.2}", dms(12.56))); 639 } 640 641 TEST(chrono_test, format_full_specs) { 642 EXPECT_EQ("1ms ", fmt::format("{:6.0}", dms(1.234))); 643 EXPECT_EQ("1.2ms ", fmt::format("{:6.1}", dms(1.234))); 644 EXPECT_EQ(" 1.23ms", fmt::format("{:>8.{}}", dms(1.234), 2)); 645 EXPECT_EQ(" 1.2ms ", fmt::format("{:^{}.{}}", dms(1.234), 7, 1)); 646 EXPECT_EQ(" 1.23ms ", fmt::format("{0:^{2}.{1}}", dms(1.234), 2, 8)); 647 EXPECT_EQ("=1.234ms=", fmt::format("{:=^{}.{}}", dms(1.234), 9, 3)); 648 EXPECT_EQ("*1.2340ms*", fmt::format("{:*^10.4}", dms(1.234))); 649 650 EXPECT_EQ("13ms ", fmt::format("{:6.0}", dms(12.56))); 651 EXPECT_EQ(" 13ms", fmt::format("{:>8.{}}", dms(12.56), 0)); 652 EXPECT_EQ(" 13ms ", fmt::format("{:^{}.{}}", dms(12.56), 6, 0)); 653 EXPECT_EQ(" 13ms ", fmt::format("{0:^{2}.{1}}", dms(12.56), 0, 8)); 654 EXPECT_EQ("==13ms===", fmt::format("{:=^{}.{}}", dms(12.56), 9, 0)); 655 EXPECT_EQ("***13ms***", fmt::format("{:*^10.0}", dms(12.56))); 656 } 657 658 TEST(chrono_test, format_simple_q) { 659 typedef std::chrono::duration<float> fs; 660 EXPECT_EQ("1.234 s", fmt::format("{:%Q %q}", fs(1.234))); 661 typedef std::chrono::duration<float, std::milli> fms; 662 EXPECT_EQ("1.234 ms", fmt::format("{:%Q %q}", fms(1.234))); 663 typedef std::chrono::duration<double> ds; 664 EXPECT_EQ("1.234 s", fmt::format("{:%Q %q}", ds(1.234))); 665 EXPECT_EQ("1.234 ms", fmt::format("{:%Q %q}", dms(1.234))); 666 } 667 668 TEST(chrono_test, format_precision_q) { 669 EXPECT_THROW_MSG( 670 (void)fmt::format(runtime("{:.2%Q %q}"), std::chrono::seconds(42)), 671 fmt::format_error, "precision not allowed for this argument type"); 672 EXPECT_EQ("1.2 ms", fmt::format("{:.1%Q %q}", dms(1.234))); 673 EXPECT_EQ("1.23 ms", fmt::format("{:.{}%Q %q}", dms(1.234), 2)); 674 } 675 676 TEST(chrono_test, format_full_specs_q) { 677 EXPECT_EQ("1 ms ", fmt::format("{:7.0%Q %q}", dms(1.234))); 678 EXPECT_EQ("1.2 ms ", fmt::format("{:7.1%Q %q}", dms(1.234))); 679 EXPECT_EQ(" 1.23 ms", fmt::format("{:>8.{}%Q %q}", dms(1.234), 2)); 680 EXPECT_EQ(" 1.2 ms ", fmt::format("{:^{}.{}%Q %q}", dms(1.234), 8, 1)); 681 EXPECT_EQ(" 1.23 ms ", fmt::format("{0:^{2}.{1}%Q %q}", dms(1.234), 2, 9)); 682 EXPECT_EQ("=1.234 ms=", fmt::format("{:=^{}.{}%Q %q}", dms(1.234), 10, 3)); 683 EXPECT_EQ("*1.2340 ms*", fmt::format("{:*^11.4%Q %q}", dms(1.234))); 684 685 EXPECT_EQ("13 ms ", fmt::format("{:7.0%Q %q}", dms(12.56))); 686 EXPECT_EQ(" 13 ms", fmt::format("{:>8.{}%Q %q}", dms(12.56), 0)); 687 EXPECT_EQ(" 13 ms ", fmt::format("{:^{}.{}%Q %q}", dms(12.56), 8, 0)); 688 EXPECT_EQ(" 13 ms ", fmt::format("{0:^{2}.{1}%Q %q}", dms(12.56), 0, 9)); 689 EXPECT_EQ("==13 ms==", fmt::format("{:=^{}.{}%Q %q}", dms(12.56), 9, 0)); 690 EXPECT_EQ("***13 ms***", fmt::format("{:*^11.0%Q %q}", dms(12.56))); 691 } 692 693 TEST(chrono_test, invalid_width_id) { 694 EXPECT_THROW((void)fmt::format(runtime("{:{o}"), std::chrono::seconds(0)), 695 fmt::format_error); 696 } 697 698 TEST(chrono_test, invalid_colons) { 699 EXPECT_THROW((void)fmt::format(runtime("{0}=:{0::"), std::chrono::seconds(0)), 700 fmt::format_error); 701 } 702 703 TEST(chrono_test, negative_durations) { 704 EXPECT_EQ("-12345", fmt::format("{:%Q}", std::chrono::seconds(-12345))); 705 EXPECT_EQ("-03:25:45", 706 fmt::format("{:%H:%M:%S}", std::chrono::seconds(-12345))); 707 EXPECT_EQ("-00:01", 708 fmt::format("{:%M:%S}", std::chrono::duration<double>(-1))); 709 EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(-12345))); 710 EXPECT_EQ("-00.127", 711 fmt::format("{:%S}", 712 std::chrono::duration<signed char, std::milli>{-127})); 713 auto min = std::numeric_limits<int>::min(); 714 EXPECT_EQ(fmt::format("{}", min), 715 fmt::format("{:%Q}", std::chrono::duration<int>(min))); 716 } 717 718 TEST(chrono_test, special_durations) { 719 auto value = fmt::format("{:%S}", std::chrono::duration<double>(1e20)); 720 EXPECT_EQ(value, "40"); 721 auto nan = std::numeric_limits<double>::quiet_NaN(); 722 EXPECT_EQ( 723 "nan nan nan nan nan:nan nan", 724 fmt::format("{:%I %H %M %S %R %r}", std::chrono::duration<double>(nan))); 725 EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::exa>(1)), 726 "1Es"); 727 EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::atto>(1)), 728 "1as"); 729 EXPECT_EQ(fmt::format("{:%R}", std::chrono::duration<char, std::mega>{2}), 730 "03:33"); 731 EXPECT_EQ(fmt::format("{:%T}", std::chrono::duration<char, std::mega>{2}), 732 "03:33:20"); 733 EXPECT_EQ("01.234", 734 fmt::format("{:.3%S}", std::chrono::duration<float, std::pico>( 735 1.234e12))); 736 } 737 738 TEST(chrono_test, unsigned_duration) { 739 EXPECT_EQ("42s", fmt::format("{}", std::chrono::duration<unsigned>(42))); 740 } 741 742 TEST(chrono_test, weekday) { 743 auto loc = get_locale("ru_RU.UTF-8"); 744 std::locale::global(loc); 745 auto mon = fmt::weekday(1); 746 747 auto tm = std::tm(); 748 tm.tm_wday = static_cast<int>(mon.c_encoding()); 749 750 EXPECT_EQ(fmt::format("{}", mon), "Mon"); 751 EXPECT_EQ(fmt::format("{:%a}", tm), "Mon"); 752 753 if (loc != std::locale::classic()) { 754 EXPECT_THAT((std::vector<std::string>{"пн", "Пн", "пнд", "Пнд"}), 755 Contains(fmt::format(loc, "{:L}", mon))); 756 EXPECT_THAT((std::vector<std::string>{"пн", "Пн", "пнд", "Пнд"}), 757 Contains(fmt::format(loc, "{:%a}", tm))); 758 } 759 } 760 761 TEST(chrono_test, cpp20_duration_subsecond_support) { 762 using attoseconds = std::chrono::duration<long long, std::atto>; 763 // Check that 18 digits of subsecond precision are supported. 764 EXPECT_EQ(fmt::format("{:%S}", attoseconds{999999999999999999}), 765 "00.999999999999999999"); 766 EXPECT_EQ(fmt::format("{:%S}", attoseconds{673231113420148734}), 767 "00.673231113420148734"); 768 EXPECT_EQ(fmt::format("{:%S}", attoseconds{-673231113420148734}), 769 "-00.673231113420148734"); 770 EXPECT_EQ(fmt::format("{:%S}", std::chrono::nanoseconds{13420148734}), 771 "13.420148734"); 772 EXPECT_EQ(fmt::format("{:%S}", std::chrono::nanoseconds{-13420148734}), 773 "-13.420148734"); 774 EXPECT_EQ(fmt::format("{:%S}", std::chrono::milliseconds{1234}), "01.234"); 775 // Check subsecond presision modifier. 776 EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::nanoseconds{1234}), 777 "00.000001"); 778 EXPECT_EQ(fmt::format("{:.18%S}", std::chrono::nanoseconds{1234}), 779 "00.000001234000000000"); 780 EXPECT_EQ(fmt::format("{:.{}%S}", std::chrono::nanoseconds{1234}, 6), 781 "00.000001"); 782 EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{1234}), 783 "01.234000"); 784 EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{-1234}), 785 "-01.234000"); 786 EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::seconds{1234}), "34.000"); 787 EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::hours{1234}), "00.000"); 788 EXPECT_EQ(fmt::format("{:.5%S}", dms(1.234)), "00.00123"); 789 EXPECT_EQ(fmt::format("{:.8%S}", dms(1.234)), "00.00123400"); 790 { 791 // Check that {:%H:%M:%S} is equivalent to {:%T}. 792 auto dur = std::chrono::milliseconds{3601234}; 793 auto formatted_dur = fmt::format("{:%T}", dur); 794 EXPECT_EQ(formatted_dur, "01:00:01.234"); 795 EXPECT_EQ(fmt::format("{:%H:%M:%S}", dur), formatted_dur); 796 EXPECT_EQ(fmt::format("{:.6%H:%M:%S}", dur), "01:00:01.234000"); 797 } 798 using nanoseconds_dbl = std::chrono::duration<double, std::nano>; 799 EXPECT_EQ(fmt::format("{:%S}", nanoseconds_dbl{-123456789}), "-00.123456789"); 800 EXPECT_EQ(fmt::format("{:%S}", nanoseconds_dbl{9123456789}), "09.123456789"); 801 // Verify that only the seconds part is extracted and printed. 802 EXPECT_EQ(fmt::format("{:%S}", nanoseconds_dbl{99123456789}), "39.123456789"); 803 EXPECT_EQ(fmt::format("{:%S}", nanoseconds_dbl{99123000000}), "39.123000000"); 804 { 805 // Now the hour is printed, and we also test if negative doubles work. 806 auto dur = nanoseconds_dbl{-99123456789}; 807 auto formatted_dur = fmt::format("{:%T}", dur); 808 EXPECT_EQ(formatted_dur, "-00:01:39.123456789"); 809 EXPECT_EQ(fmt::format("{:%H:%M:%S}", dur), formatted_dur); 810 EXPECT_EQ(fmt::format("{:.3%H:%M:%S}", dur), "-00:01:39.123"); 811 } 812 // Check that durations with precision greater than std::chrono::seconds have 813 // fixed precision, and print zeros even if there is no fractional part. 814 EXPECT_EQ(fmt::format("{:%S}", std::chrono::microseconds{7000000}), 815 "07.000000"); 816 EXPECT_EQ(fmt::format("{:%S}", 817 std::chrono::duration<long long, std::ratio<1, 3>>(1)), 818 "00.333333"); 819 EXPECT_EQ(fmt::format("{:%S}", 820 std::chrono::duration<long long, std::ratio<1, 7>>(1)), 821 "00.142857"); 822 823 EXPECT_EQ( 824 fmt::format("{:%S}", 825 std::chrono::duration<signed char, std::ratio<1, 100>>(0x80)), 826 "-01.28"); 827 828 EXPECT_EQ( 829 fmt::format("{:%M:%S}", 830 std::chrono::duration<short, std::ratio<1, 100>>(0x8000)), 831 "-05:27.68"); 832 833 // Check that floating point seconds with ratio<1,1> are printed. 834 EXPECT_EQ(fmt::format("{:%S}", std::chrono::duration<double>{1.5}), 835 "01.500000"); 836 EXPECT_EQ(fmt::format("{:%M:%S}", std::chrono::duration<double>{-61.25}), 837 "-01:01.250000"); 838 } 839 840 #endif // FMT_STATIC_THOUSANDS_SEPARATOR 841 842 // Disable the utc_clock test for windows, as the icu.dll used for tzdb 843 // (time zone database) is not shipped with many windows versions. 844 #if FMT_USE_UTC_TIME && !defined(_WIN32) 845 TEST(chrono_test, utc_clock) { 846 auto t1 = std::chrono::system_clock::now(); 847 auto t1_utc = std::chrono::utc_clock::from_sys(t1); 848 EXPECT_EQ(fmt::format("{:%Y-%m-%d %H:%M:%S}", t1), 849 fmt::format("{:%Y-%m-%d %H:%M:%S}", t1_utc)); 850 } 851 #endif 852 853 TEST(chrono_test, timestamps_ratios) { 854 std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> 855 t1(std::chrono::milliseconds(67890)); 856 857 EXPECT_EQ(fmt::format("{:%M:%S}", t1), "01:07.890"); 858 859 std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes> 860 t2(std::chrono::minutes(7)); 861 862 EXPECT_EQ(fmt::format("{:%M:%S}", t2), "07:00"); 863 864 std::chrono::time_point<std::chrono::system_clock, 865 std::chrono::duration<int, std::ratio<9>>> 866 t3(std::chrono::duration<int, std::ratio<9>>(7)); 867 868 EXPECT_EQ(fmt::format("{:%M:%S}", t3), "01:03"); 869 870 std::chrono::time_point<std::chrono::system_clock, 871 std::chrono::duration<int, std::ratio<63>>> 872 t4(std::chrono::duration<int, std::ratio<63>>(1)); 873 874 EXPECT_EQ(fmt::format("{:%M:%S}", t4), "01:03"); 875 } 876 877 TEST(chrono_test, timestamps_sub_seconds) { 878 std::chrono::time_point<std::chrono::system_clock, 879 std::chrono::duration<long long, std::ratio<1, 3>>> 880 t1(std::chrono::duration<long long, std::ratio<1, 3>>(4)); 881 882 EXPECT_EQ(fmt::format("{:%S}", t1), "01.333333"); 883 884 std::chrono::time_point<std::chrono::system_clock, 885 std::chrono::duration<double, std::ratio<1, 3>>> 886 t2(std::chrono::duration<double, std::ratio<1, 3>>(4)); 887 888 EXPECT_EQ(fmt::format("{:%S}", t2), "01.333333"); 889 890 const std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> 891 t3(std::chrono::seconds(2)); 892 893 EXPECT_EQ(fmt::format("{:%S}", t3), "02"); 894 895 const std::chrono::time_point<std::chrono::system_clock, 896 std::chrono::duration<double>> 897 t4(std::chrono::duration<double, std::ratio<1, 1>>(9.5)); 898 899 EXPECT_EQ(fmt::format("{:%S}", t4), "09.500000"); 900 901 const std::chrono::time_point<std::chrono::system_clock, 902 std::chrono::duration<double>> 903 t5(std::chrono::duration<double, std::ratio<1, 1>>(9)); 904 905 EXPECT_EQ(fmt::format("{:%S}", t5), "09"); 906 907 const std::chrono::time_point<std::chrono::system_clock, 908 std::chrono::milliseconds> 909 t6(std::chrono::seconds(1) + std::chrono::milliseconds(120)); 910 911 EXPECT_EQ(fmt::format("{:%S}", t6), "01.120"); 912 913 const std::chrono::time_point<std::chrono::system_clock, 914 std::chrono::microseconds> 915 t7(std::chrono::microseconds(1234567)); 916 917 EXPECT_EQ(fmt::format("{:%S}", t7), "01.234567"); 918 919 const std::chrono::time_point<std::chrono::system_clock, 920 std::chrono::nanoseconds> 921 t8(std::chrono::nanoseconds(123456789)); 922 923 EXPECT_EQ(fmt::format("{:%S}", t8), "00.123456789"); 924 925 const auto t9 = std::chrono::time_point_cast<std::chrono::nanoseconds>( 926 std::chrono::system_clock::now()); 927 const auto t9_sec = std::chrono::time_point_cast<std::chrono::seconds>(t9); 928 auto t9_sub_sec_part = fmt::format("{0:09}", (t9 - t9_sec).count()); 929 930 EXPECT_EQ(fmt::format("{}.{}", strftime_full_utc(t9_sec), t9_sub_sec_part), 931 fmt::format("{:%Y-%m-%d %H:%M:%S}", t9)); 932 EXPECT_EQ(fmt::format("{}.{}", strftime_full_utc(t9_sec), t9_sub_sec_part), 933 fmt::format("{:%Y-%m-%d %T}", t9)); 934 935 const std::chrono::time_point<std::chrono::system_clock, 936 std::chrono::milliseconds> 937 t10(std::chrono::milliseconds(2000)); 938 939 EXPECT_EQ(fmt::format("{:%S}", t10), "02.000"); 940 941 { 942 const auto epoch = std::chrono::time_point<std::chrono::system_clock, 943 std::chrono::milliseconds>(); 944 const auto d = std::chrono::milliseconds(250); 945 946 EXPECT_EQ("59.750", fmt::format("{:%S}", epoch - d)); 947 EXPECT_EQ("00.000", fmt::format("{:%S}", epoch)); 948 EXPECT_EQ("00.250", fmt::format("{:%S}", epoch + d)); 949 } 950 } 951 952 TEST(chrono_test, glibc_extensions) { 953 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%0}"), std::chrono::seconds()), 954 fmt::format_error, "invalid format"); 955 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%_}"), std::chrono::seconds()), 956 fmt::format_error, "invalid format"); 957 EXPECT_THROW_MSG((void)fmt::format(runtime("{:%-}"), std::chrono::seconds()), 958 fmt::format_error, "invalid format"); 959 960 { 961 const auto d = std::chrono::hours(1) + std::chrono::minutes(2) + 962 std::chrono::seconds(3); 963 964 EXPECT_EQ(fmt::format("{:%I,%H,%M,%S}", d), "01,01,02,03"); 965 EXPECT_EQ(fmt::format("{:%0I,%0H,%0M,%0S}", d), "01,01,02,03"); 966 EXPECT_EQ(fmt::format("{:%_I,%_H,%_M,%_S}", d), " 1, 1, 2, 3"); 967 EXPECT_EQ(fmt::format("{:%-I,%-H,%-M,%-S}", d), "1,1,2,3"); 968 969 EXPECT_EQ(fmt::format("{:%OI,%OH,%OM,%OS}", d), "01,01,02,03"); 970 EXPECT_EQ(fmt::format("{:%0OI,%0OH,%0OM,%0OS}", d), "01,01,02,03"); 971 EXPECT_EQ(fmt::format("{:%_OI,%_OH,%_OM,%_OS}", d), " 1, 1, 2, 3"); 972 EXPECT_EQ(fmt::format("{:%-OI,%-OH,%-OM,%-OS}", d), "1,1,2,3"); 973 } 974 975 { 976 const auto tm = make_tm(1970, 1, 1, 1, 2, 3); 977 EXPECT_EQ(fmt::format("{:%I,%H,%M,%S}", tm), "01,01,02,03"); 978 EXPECT_EQ(fmt::format("{:%0I,%0H,%0M,%0S}", tm), "01,01,02,03"); 979 EXPECT_EQ(fmt::format("{:%_I,%_H,%_M,%_S}", tm), " 1, 1, 2, 3"); 980 EXPECT_EQ(fmt::format("{:%-I,%-H,%-M,%-S}", tm), "1,1,2,3"); 981 982 EXPECT_EQ(fmt::format("{:%OI,%OH,%OM,%OS}", tm), "01,01,02,03"); 983 EXPECT_EQ(fmt::format("{:%0OI,%0OH,%0OM,%0OS}", tm), "01,01,02,03"); 984 EXPECT_EQ(fmt::format("{:%_OI,%_OH,%_OM,%_OS}", tm), " 1, 1, 2, 3"); 985 EXPECT_EQ(fmt::format("{:%-OI,%-OH,%-OM,%-OS}", tm), "1,1,2,3"); 986 } 987 988 { 989 const auto d = std::chrono::seconds(3) + std::chrono::milliseconds(140); 990 EXPECT_EQ(fmt::format("{:%S}", d), "03.140"); 991 EXPECT_EQ(fmt::format("{:%0S}", d), "03.140"); 992 EXPECT_EQ(fmt::format("{:%_S}", d), " 3.140"); 993 EXPECT_EQ(fmt::format("{:%-S}", d), "3.140"); 994 } 995 996 { 997 const auto d = std::chrono::duration<double>(3.14); 998 EXPECT_EQ(fmt::format("{:%S}", d), "03.140000"); 999 EXPECT_EQ(fmt::format("{:%0S}", d), "03.140000"); 1000 EXPECT_EQ(fmt::format("{:%_S}", d), " 3.140000"); 1001 EXPECT_EQ(fmt::format("{:%-S}", d), "3.140000"); 1002 } 1003 }