time_zone_format_test.cc 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588
  1. // Copyright 2016 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "cctz/time_zone.h"
  15. #include <chrono>
  16. #include <iomanip>
  17. #include <sstream>
  18. #include <string>
  19. #include "cctz/civil_time.h"
  20. #include "gmock/gmock.h"
  21. #include "gtest/gtest.h"
  22. namespace chrono = std::chrono;
  23. namespace cctz {
  24. namespace {
  25. // This helper is a macro so that failed expectations show up with the
  26. // correct line numbers.
  27. #define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \
  28. do { \
  29. time_zone::absolute_lookup al = tz.lookup(tp); \
  30. EXPECT_EQ(y, al.cs.year()); \
  31. EXPECT_EQ(m, al.cs.month()); \
  32. EXPECT_EQ(d, al.cs.day()); \
  33. EXPECT_EQ(hh, al.cs.hour()); \
  34. EXPECT_EQ(mm, al.cs.minute()); \
  35. EXPECT_EQ(ss, al.cs.second()); \
  36. EXPECT_EQ(off, al.offset); \
  37. EXPECT_TRUE(isdst == al.is_dst); \
  38. EXPECT_STREQ(zone, al.abbr); \
  39. } while (0)
  40. const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
  41. const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
  42. const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
  43. const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
  44. // A helper that tests the given format specifier by itself, and with leading
  45. // and trailing characters. For example: TestFormatSpecifier(tp, "%a", "Thu").
  46. template <typename D>
  47. void TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt,
  48. const std::string& ans) {
  49. EXPECT_EQ(ans, cctz::format(fmt, tp, tz)) << fmt;
  50. EXPECT_EQ("xxx " + ans, cctz::format("xxx " + fmt, tp, tz));
  51. EXPECT_EQ(ans + " yyy", cctz::format(fmt + " yyy", tp, tz));
  52. EXPECT_EQ("xxx " + ans + " yyy", cctz::format("xxx " + fmt + " yyy", tp, tz));
  53. }
  54. } // namespace
  55. //
  56. // Testing format()
  57. //
  58. TEST(Format, TimePointResolution) {
  59. const char kFmt[] = "%H:%M:%E*S";
  60. const time_zone utc = utc_time_zone();
  61. const time_point<chrono::nanoseconds> t0 =
  62. chrono::system_clock::from_time_t(1420167845) +
  63. chrono::milliseconds(123) + chrono::microseconds(456) +
  64. chrono::nanoseconds(789);
  65. EXPECT_EQ(
  66. "03:04:05.123456789",
  67. cctz::format(kFmt, chrono::time_point_cast<chrono::nanoseconds>(t0), utc));
  68. EXPECT_EQ(
  69. "03:04:05.123456",
  70. cctz::format(kFmt, chrono::time_point_cast<chrono::microseconds>(t0), utc));
  71. EXPECT_EQ(
  72. "03:04:05.123",
  73. cctz::format(kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc));
  74. EXPECT_EQ("03:04:05",
  75. cctz::format(kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc));
  76. EXPECT_EQ("03:04:05",
  77. cctz::format(kFmt, chrono::time_point_cast<cctz::seconds>(t0), utc));
  78. EXPECT_EQ("03:04:00",
  79. cctz::format(kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc));
  80. EXPECT_EQ("03:00:00",
  81. cctz::format(kFmt, chrono::time_point_cast<chrono::hours>(t0), utc));
  82. }
  83. TEST(Format, TimePointExtendedResolution) {
  84. const char kFmt[] = "%H:%M:%E*S";
  85. const time_zone utc = utc_time_zone();
  86. const time_point<cctz::seconds> tp =
  87. chrono::time_point_cast<cctz::seconds>(
  88. chrono::system_clock::from_time_t(0)) +
  89. chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56);
  90. EXPECT_EQ(
  91. "12:34:56.123456789012345",
  92. detail::format(kFmt, tp, detail::femtoseconds(123456789012345), utc));
  93. EXPECT_EQ(
  94. "12:34:56.012345678901234",
  95. detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc));
  96. EXPECT_EQ(
  97. "12:34:56.001234567890123",
  98. detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));
  99. EXPECT_EQ(
  100. "12:34:56.000123456789012",
  101. detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));
  102. EXPECT_EQ("12:34:56.000000000000123",
  103. detail::format(kFmt, tp, detail::femtoseconds(123), utc));
  104. EXPECT_EQ("12:34:56.000000000000012",
  105. detail::format(kFmt, tp, detail::femtoseconds(12), utc));
  106. EXPECT_EQ("12:34:56.000000000000001",
  107. detail::format(kFmt, tp, detail::femtoseconds(1), utc));
  108. }
  109. TEST(Format, Basics) {
  110. time_zone tz = utc_time_zone();
  111. time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
  112. // Starts with a couple basic edge cases.
  113. EXPECT_EQ("", cctz::format("", tp, tz));
  114. EXPECT_EQ(" ", cctz::format(" ", tp, tz));
  115. EXPECT_EQ(" ", cctz::format(" ", tp, tz));
  116. EXPECT_EQ("xxx", cctz::format("xxx", tp, tz));
  117. std::string big(128, 'x');
  118. EXPECT_EQ(big, cctz::format(big, tp, tz));
  119. // Cause the 1024-byte buffer to grow.
  120. std::string bigger(100000, 'x');
  121. EXPECT_EQ(bigger, cctz::format(bigger, tp, tz));
  122. tp += chrono::hours(13) + chrono::minutes(4) + chrono::seconds(5);
  123. tp += chrono::milliseconds(6) + chrono::microseconds(7) +
  124. chrono::nanoseconds(8);
  125. EXPECT_EQ("1970-01-01", cctz::format("%Y-%m-%d", tp, tz));
  126. EXPECT_EQ("13:04:05", cctz::format("%H:%M:%S", tp, tz));
  127. EXPECT_EQ("13:04:05.006", cctz::format("%H:%M:%E3S", tp, tz));
  128. EXPECT_EQ("13:04:05.006007", cctz::format("%H:%M:%E6S", tp, tz));
  129. EXPECT_EQ("13:04:05.006007008", cctz::format("%H:%M:%E9S", tp, tz));
  130. }
  131. TEST(Format, PosixConversions) {
  132. const time_zone tz = utc_time_zone();
  133. auto tp = chrono::system_clock::from_time_t(0);
  134. TestFormatSpecifier(tp, tz, "%d", "01");
  135. TestFormatSpecifier(tp, tz, "%e", " 1"); // extension but internal support
  136. TestFormatSpecifier(tp, tz, "%H", "00");
  137. TestFormatSpecifier(tp, tz, "%I", "12");
  138. TestFormatSpecifier(tp, tz, "%j", "001");
  139. TestFormatSpecifier(tp, tz, "%m", "01");
  140. TestFormatSpecifier(tp, tz, "%M", "00");
  141. TestFormatSpecifier(tp, tz, "%S", "00");
  142. TestFormatSpecifier(tp, tz, "%U", "00");
  143. TestFormatSpecifier(tp, tz, "%w", "4"); // 4=Thursday
  144. TestFormatSpecifier(tp, tz, "%W", "00");
  145. TestFormatSpecifier(tp, tz, "%y", "70");
  146. TestFormatSpecifier(tp, tz, "%Y", "1970");
  147. TestFormatSpecifier(tp, tz, "%z", "+0000");
  148. TestFormatSpecifier(tp, tz, "%Z", "UTC");
  149. TestFormatSpecifier(tp, tz, "%%", "%");
  150. #if defined(__linux__)
  151. // SU/C99/TZ extensions
  152. TestFormatSpecifier(tp, tz, "%C", "19");
  153. TestFormatSpecifier(tp, tz, "%D", "01/01/70");
  154. TestFormatSpecifier(tp, tz, "%F", "1970-01-01");
  155. TestFormatSpecifier(tp, tz, "%g", "70");
  156. TestFormatSpecifier(tp, tz, "%G", "1970");
  157. TestFormatSpecifier(tp, tz, "%k", " 0");
  158. TestFormatSpecifier(tp, tz, "%l", "12");
  159. TestFormatSpecifier(tp, tz, "%n", "\n");
  160. TestFormatSpecifier(tp, tz, "%R", "00:00");
  161. TestFormatSpecifier(tp, tz, "%t", "\t");
  162. TestFormatSpecifier(tp, tz, "%T", "00:00:00");
  163. TestFormatSpecifier(tp, tz, "%u", "4"); // 4=Thursday
  164. TestFormatSpecifier(tp, tz, "%V", "01");
  165. TestFormatSpecifier(tp, tz, "%s", "0");
  166. #endif
  167. }
  168. TEST(Format, LocaleSpecific) {
  169. const time_zone tz = utc_time_zone();
  170. auto tp = chrono::system_clock::from_time_t(0);
  171. TestFormatSpecifier(tp, tz, "%a", "Thu");
  172. TestFormatSpecifier(tp, tz, "%A", "Thursday");
  173. TestFormatSpecifier(tp, tz, "%b", "Jan");
  174. TestFormatSpecifier(tp, tz, "%B", "January");
  175. // %c should at least produce the numeric year and time-of-day.
  176. const std::string s = cctz::format("%c", tp, utc_time_zone());
  177. EXPECT_THAT(s, testing::HasSubstr("1970"));
  178. EXPECT_THAT(s, testing::HasSubstr("00:00:00"));
  179. TestFormatSpecifier(tp, tz, "%p", "AM");
  180. TestFormatSpecifier(tp, tz, "%x", "01/01/70");
  181. TestFormatSpecifier(tp, tz, "%X", "00:00:00");
  182. #if defined(__linux__)
  183. // SU/C99/TZ extensions
  184. TestFormatSpecifier(tp, tz, "%h", "Jan"); // Same as %b
  185. TestFormatSpecifier(tp, tz, "%P", "am");
  186. TestFormatSpecifier(tp, tz, "%r", "12:00:00 AM");
  187. // Modified conversion specifiers %E_
  188. TestFormatSpecifier(tp, tz, "%Ec", "Thu Jan 1 00:00:00 1970");
  189. TestFormatSpecifier(tp, tz, "%EC", "19");
  190. TestFormatSpecifier(tp, tz, "%Ex", "01/01/70");
  191. TestFormatSpecifier(tp, tz, "%EX", "00:00:00");
  192. TestFormatSpecifier(tp, tz, "%Ey", "70");
  193. TestFormatSpecifier(tp, tz, "%EY", "1970");
  194. // Modified conversion specifiers %O_
  195. TestFormatSpecifier(tp, tz, "%Od", "01");
  196. TestFormatSpecifier(tp, tz, "%Oe", " 1");
  197. TestFormatSpecifier(tp, tz, "%OH", "00");
  198. TestFormatSpecifier(tp, tz, "%OI", "12");
  199. TestFormatSpecifier(tp, tz, "%Om", "01");
  200. TestFormatSpecifier(tp, tz, "%OM", "00");
  201. TestFormatSpecifier(tp, tz, "%OS", "00");
  202. TestFormatSpecifier(tp, tz, "%Ou", "4"); // 4=Thursday
  203. TestFormatSpecifier(tp, tz, "%OU", "00");
  204. TestFormatSpecifier(tp, tz, "%OV", "01");
  205. TestFormatSpecifier(tp, tz, "%Ow", "4"); // 4=Thursday
  206. TestFormatSpecifier(tp, tz, "%OW", "00");
  207. TestFormatSpecifier(tp, tz, "%Oy", "70");
  208. #endif
  209. }
  210. TEST(Format, Escaping) {
  211. const time_zone tz = utc_time_zone();
  212. auto tp = chrono::system_clock::from_time_t(0);
  213. TestFormatSpecifier(tp, tz, "%%", "%");
  214. TestFormatSpecifier(tp, tz, "%%a", "%a");
  215. TestFormatSpecifier(tp, tz, "%%b", "%b");
  216. TestFormatSpecifier(tp, tz, "%%Ea", "%Ea");
  217. TestFormatSpecifier(tp, tz, "%%Es", "%Es");
  218. TestFormatSpecifier(tp, tz, "%%E3S", "%E3S");
  219. TestFormatSpecifier(tp, tz, "%%OS", "%OS");
  220. TestFormatSpecifier(tp, tz, "%%O3S", "%O3S");
  221. // Multiple levels of escaping.
  222. TestFormatSpecifier(tp, tz, "%%%Y", "%1970");
  223. TestFormatSpecifier(tp, tz, "%%%E3S", "%00.000");
  224. TestFormatSpecifier(tp, tz, "%%%%E3S", "%%E3S");
  225. }
  226. TEST(Format, ExtendedSeconds) {
  227. const time_zone tz = utc_time_zone();
  228. // No subseconds.
  229. time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
  230. tp += chrono::seconds(5);
  231. EXPECT_EQ("05", cctz::format("%E*S", tp, tz));
  232. EXPECT_EQ("05", cctz::format("%E0S", tp, tz));
  233. EXPECT_EQ("05.0", cctz::format("%E1S", tp, tz));
  234. EXPECT_EQ("05.00", cctz::format("%E2S", tp, tz));
  235. EXPECT_EQ("05.000", cctz::format("%E3S", tp, tz));
  236. EXPECT_EQ("05.0000", cctz::format("%E4S", tp, tz));
  237. EXPECT_EQ("05.00000", cctz::format("%E5S", tp, tz));
  238. EXPECT_EQ("05.000000", cctz::format("%E6S", tp, tz));
  239. EXPECT_EQ("05.0000000", cctz::format("%E7S", tp, tz));
  240. EXPECT_EQ("05.00000000", cctz::format("%E8S", tp, tz));
  241. EXPECT_EQ("05.000000000", cctz::format("%E9S", tp, tz));
  242. EXPECT_EQ("05.0000000000", cctz::format("%E10S", tp, tz));
  243. EXPECT_EQ("05.00000000000", cctz::format("%E11S", tp, tz));
  244. EXPECT_EQ("05.000000000000", cctz::format("%E12S", tp, tz));
  245. EXPECT_EQ("05.0000000000000", cctz::format("%E13S", tp, tz));
  246. EXPECT_EQ("05.00000000000000", cctz::format("%E14S", tp, tz));
  247. EXPECT_EQ("05.000000000000000", cctz::format("%E15S", tp, tz));
  248. // With subseconds.
  249. tp += chrono::milliseconds(6) + chrono::microseconds(7) +
  250. chrono::nanoseconds(8);
  251. EXPECT_EQ("05.006007008", cctz::format("%E*S", tp, tz));
  252. EXPECT_EQ("05", cctz::format("%E0S", tp, tz));
  253. EXPECT_EQ("05.0", cctz::format("%E1S", tp, tz));
  254. EXPECT_EQ("05.00", cctz::format("%E2S", tp, tz));
  255. EXPECT_EQ("05.006", cctz::format("%E3S", tp, tz));
  256. EXPECT_EQ("05.0060", cctz::format("%E4S", tp, tz));
  257. EXPECT_EQ("05.00600", cctz::format("%E5S", tp, tz));
  258. EXPECT_EQ("05.006007", cctz::format("%E6S", tp, tz));
  259. EXPECT_EQ("05.0060070", cctz::format("%E7S", tp, tz));
  260. EXPECT_EQ("05.00600700", cctz::format("%E8S", tp, tz));
  261. EXPECT_EQ("05.006007008", cctz::format("%E9S", tp, tz));
  262. EXPECT_EQ("05.0060070080", cctz::format("%E10S", tp, tz));
  263. EXPECT_EQ("05.00600700800", cctz::format("%E11S", tp, tz));
  264. EXPECT_EQ("05.006007008000", cctz::format("%E12S", tp, tz));
  265. EXPECT_EQ("05.0060070080000", cctz::format("%E13S", tp, tz));
  266. EXPECT_EQ("05.00600700800000", cctz::format("%E14S", tp, tz));
  267. EXPECT_EQ("05.006007008000000", cctz::format("%E15S", tp, tz));
  268. // Times before the Unix epoch.
  269. tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1);
  270. EXPECT_EQ("1969-12-31 23:59:59.999999",
  271. cctz::format("%Y-%m-%d %H:%M:%E*S", tp, tz));
  272. // Here is a "%E*S" case we got wrong for a while. While the first
  273. // instant below is correctly rendered as "...:07.333304", the second
  274. // one used to appear as "...:07.33330499999999999".
  275. tp = chrono::system_clock::from_time_t(0) +
  276. chrono::microseconds(1395024427333304);
  277. EXPECT_EQ("2014-03-17 02:47:07.333304",
  278. cctz::format("%Y-%m-%d %H:%M:%E*S", tp, tz));
  279. tp += chrono::microseconds(1);
  280. EXPECT_EQ("2014-03-17 02:47:07.333305",
  281. cctz::format("%Y-%m-%d %H:%M:%E*S", tp, tz));
  282. }
  283. TEST(Format, ExtendedSubeconds) {
  284. const time_zone tz = utc_time_zone();
  285. // No subseconds.
  286. time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
  287. tp += chrono::seconds(5);
  288. EXPECT_EQ("0", cctz::format("%E*f", tp, tz));
  289. EXPECT_EQ("", cctz::format("%E0f", tp, tz));
  290. EXPECT_EQ("0", cctz::format("%E1f", tp, tz));
  291. EXPECT_EQ("00", cctz::format("%E2f", tp, tz));
  292. EXPECT_EQ("000", cctz::format("%E3f", tp, tz));
  293. EXPECT_EQ("0000", cctz::format("%E4f", tp, tz));
  294. EXPECT_EQ("00000", cctz::format("%E5f", tp, tz));
  295. EXPECT_EQ("000000", cctz::format("%E6f", tp, tz));
  296. EXPECT_EQ("0000000", cctz::format("%E7f", tp, tz));
  297. EXPECT_EQ("00000000", cctz::format("%E8f", tp, tz));
  298. EXPECT_EQ("000000000", cctz::format("%E9f", tp, tz));
  299. EXPECT_EQ("0000000000", cctz::format("%E10f", tp, tz));
  300. EXPECT_EQ("00000000000", cctz::format("%E11f", tp, tz));
  301. EXPECT_EQ("000000000000", cctz::format("%E12f", tp, tz));
  302. EXPECT_EQ("0000000000000", cctz::format("%E13f", tp, tz));
  303. EXPECT_EQ("00000000000000", cctz::format("%E14f", tp, tz));
  304. EXPECT_EQ("000000000000000", cctz::format("%E15f", tp, tz));
  305. // With subseconds.
  306. tp += chrono::milliseconds(6) + chrono::microseconds(7) +
  307. chrono::nanoseconds(8);
  308. EXPECT_EQ("006007008", cctz::format("%E*f", tp, tz));
  309. EXPECT_EQ("", cctz::format("%E0f", tp, tz));
  310. EXPECT_EQ("0", cctz::format("%E1f", tp, tz));
  311. EXPECT_EQ("00", cctz::format("%E2f", tp, tz));
  312. EXPECT_EQ("006", cctz::format("%E3f", tp, tz));
  313. EXPECT_EQ("0060", cctz::format("%E4f", tp, tz));
  314. EXPECT_EQ("00600", cctz::format("%E5f", tp, tz));
  315. EXPECT_EQ("006007", cctz::format("%E6f", tp, tz));
  316. EXPECT_EQ("0060070", cctz::format("%E7f", tp, tz));
  317. EXPECT_EQ("00600700", cctz::format("%E8f", tp, tz));
  318. EXPECT_EQ("006007008", cctz::format("%E9f", tp, tz));
  319. EXPECT_EQ("0060070080", cctz::format("%E10f", tp, tz));
  320. EXPECT_EQ("00600700800", cctz::format("%E11f", tp, tz));
  321. EXPECT_EQ("006007008000", cctz::format("%E12f", tp, tz));
  322. EXPECT_EQ("0060070080000", cctz::format("%E13f", tp, tz));
  323. EXPECT_EQ("00600700800000", cctz::format("%E14f", tp, tz));
  324. EXPECT_EQ("006007008000000", cctz::format("%E15f", tp, tz));
  325. // Times before the Unix epoch.
  326. tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1);
  327. EXPECT_EQ("1969-12-31 23:59:59.999999",
  328. cctz::format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
  329. // Here is a "%E*S" case we got wrong for a while. While the first
  330. // instant below is correctly rendered as "...:07.333304", the second
  331. // one used to appear as "...:07.33330499999999999".
  332. tp = chrono::system_clock::from_time_t(0) +
  333. chrono::microseconds(1395024427333304);
  334. EXPECT_EQ("2014-03-17 02:47:07.333304",
  335. cctz::format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
  336. tp += chrono::microseconds(1);
  337. EXPECT_EQ("2014-03-17 02:47:07.333305",
  338. cctz::format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
  339. }
  340. TEST(Format, CompareExtendSecondsVsSubseconds) {
  341. const time_zone tz = utc_time_zone();
  342. // This test case illustrates the differences/similarities between:
  343. // fmt_A: %E<prec>S
  344. // fmt_B: %S.%E<prec>f
  345. auto fmt_A = [](const std::string& prec) { return "%E" + prec + "S"; };
  346. auto fmt_B = [](const std::string& prec) { return "%S.%E" + prec + "f"; };
  347. // No subseconds:
  348. time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
  349. tp += chrono::seconds(5);
  350. // ... %E*S and %S.%E*f are different.
  351. EXPECT_EQ("05", cctz::format(fmt_A("*"), tp, tz));
  352. EXPECT_EQ("05.0", cctz::format(fmt_B("*"), tp, tz));
  353. // ... %E0S and %S.%E0f are different.
  354. EXPECT_EQ("05", cctz::format(fmt_A("0"), tp, tz));
  355. EXPECT_EQ("05.", cctz::format(fmt_B("0"), tp, tz));
  356. // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].
  357. for (int prec = 1; prec <= 15; ++prec) {
  358. const std::string a = cctz::format(fmt_A(std::to_string(prec)), tp, tz);
  359. const std::string b = cctz::format(fmt_B(std::to_string(prec)), tp, tz);
  360. EXPECT_EQ(a, b) << "prec=" << prec;
  361. }
  362. // With subseconds:
  363. // ... %E*S and %S.%E*f are the same.
  364. tp += chrono::milliseconds(6) + chrono::microseconds(7) +
  365. chrono::nanoseconds(8);
  366. EXPECT_EQ("05.006007008", cctz::format(fmt_A("*"), tp, tz));
  367. EXPECT_EQ("05.006007008", cctz::format(fmt_B("*"), tp, tz));
  368. // ... %E0S and %S.%E0f are different.
  369. EXPECT_EQ("05", cctz::format(fmt_A("0"), tp, tz));
  370. EXPECT_EQ("05.", cctz::format(fmt_B("0"), tp, tz));
  371. // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].
  372. for (int prec = 1; prec <= 15; ++prec) {
  373. const std::string a = cctz::format(fmt_A(std::to_string(prec)), tp, tz);
  374. const std::string b = cctz::format(fmt_B(std::to_string(prec)), tp, tz);
  375. EXPECT_EQ(a, b) << "prec=" << prec;
  376. }
  377. }
  378. TEST(Format, ExtendedOffset) {
  379. const auto tp = chrono::system_clock::from_time_t(0);
  380. auto tz = fixed_time_zone(cctz::seconds::zero());
  381. TestFormatSpecifier(tp, tz, "%z", "+0000");
  382. TestFormatSpecifier(tp, tz, "%:z", "+00:00");
  383. TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
  384. tz = fixed_time_zone(chrono::seconds(56));
  385. TestFormatSpecifier(tp, tz, "%z", "+0000");
  386. TestFormatSpecifier(tp, tz, "%:z", "+00:00");
  387. TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
  388. tz = fixed_time_zone(-chrono::seconds(56)); // NOTE: +00:00
  389. TestFormatSpecifier(tp, tz, "%z", "+0000");
  390. TestFormatSpecifier(tp, tz, "%:z", "+00:00");
  391. TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
  392. tz = fixed_time_zone(chrono::minutes(34));
  393. TestFormatSpecifier(tp, tz, "%z", "+0034");
  394. TestFormatSpecifier(tp, tz, "%:z", "+00:34");
  395. TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
  396. tz = fixed_time_zone(-chrono::minutes(34));
  397. TestFormatSpecifier(tp, tz, "%z", "-0034");
  398. TestFormatSpecifier(tp, tz, "%:z", "-00:34");
  399. TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
  400. tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
  401. TestFormatSpecifier(tp, tz, "%z", "+0034");
  402. TestFormatSpecifier(tp, tz, "%:z", "+00:34");
  403. TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
  404. tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
  405. TestFormatSpecifier(tp, tz, "%z", "-0034");
  406. TestFormatSpecifier(tp, tz, "%:z", "-00:34");
  407. TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
  408. tz = fixed_time_zone(chrono::hours(12));
  409. TestFormatSpecifier(tp, tz, "%z", "+1200");
  410. TestFormatSpecifier(tp, tz, "%:z", "+12:00");
  411. TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
  412. tz = fixed_time_zone(-chrono::hours(12));
  413. TestFormatSpecifier(tp, tz, "%z", "-1200");
  414. TestFormatSpecifier(tp, tz, "%:z", "-12:00");
  415. TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
  416. tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
  417. TestFormatSpecifier(tp, tz, "%z", "+1200");
  418. TestFormatSpecifier(tp, tz, "%:z", "+12:00");
  419. TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
  420. tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
  421. TestFormatSpecifier(tp, tz, "%z", "-1200");
  422. TestFormatSpecifier(tp, tz, "%:z", "-12:00");
  423. TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
  424. tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
  425. TestFormatSpecifier(tp, tz, "%z", "+1234");
  426. TestFormatSpecifier(tp, tz, "%:z", "+12:34");
  427. TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
  428. tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
  429. TestFormatSpecifier(tp, tz, "%z", "-1234");
  430. TestFormatSpecifier(tp, tz, "%:z", "-12:34");
  431. TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
  432. tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
  433. chrono::seconds(56));
  434. TestFormatSpecifier(tp, tz, "%z", "+1234");
  435. TestFormatSpecifier(tp, tz, "%:z", "+12:34");
  436. TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
  437. tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
  438. chrono::seconds(56));
  439. TestFormatSpecifier(tp, tz, "%z", "-1234");
  440. TestFormatSpecifier(tp, tz, "%:z", "-12:34");
  441. TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
  442. }
  443. TEST(Format, ExtendedSecondOffset) {
  444. const auto tp = chrono::system_clock::from_time_t(0);
  445. auto tz = fixed_time_zone(cctz::seconds::zero());
  446. TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00");
  447. TestFormatSpecifier(tp, tz, "%::z", "+00:00:00");
  448. TestFormatSpecifier(tp, tz, "%:::z", "+00");
  449. tz = fixed_time_zone(chrono::seconds(56));
  450. TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56");
  451. TestFormatSpecifier(tp, tz, "%::z", "+00:00:56");
  452. TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56");
  453. tz = fixed_time_zone(-chrono::seconds(56));
  454. TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56");
  455. TestFormatSpecifier(tp, tz, "%::z", "-00:00:56");
  456. TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56");
  457. tz = fixed_time_zone(chrono::minutes(34));
  458. TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00");
  459. TestFormatSpecifier(tp, tz, "%::z", "+00:34:00");
  460. TestFormatSpecifier(tp, tz, "%:::z", "+00:34");
  461. tz = fixed_time_zone(-chrono::minutes(34));
  462. TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00");
  463. TestFormatSpecifier(tp, tz, "%::z", "-00:34:00");
  464. TestFormatSpecifier(tp, tz, "%:::z", "-00:34");
  465. tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
  466. TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56");
  467. TestFormatSpecifier(tp, tz, "%::z", "+00:34:56");
  468. TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56");
  469. tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
  470. TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56");
  471. TestFormatSpecifier(tp, tz, "%::z", "-00:34:56");
  472. TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56");
  473. tz = fixed_time_zone(chrono::hours(12));
  474. TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00");
  475. TestFormatSpecifier(tp, tz, "%::z", "+12:00:00");
  476. TestFormatSpecifier(tp, tz, "%:::z", "+12");
  477. tz = fixed_time_zone(-chrono::hours(12));
  478. TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00");
  479. TestFormatSpecifier(tp, tz, "%::z", "-12:00:00");
  480. TestFormatSpecifier(tp, tz, "%:::z", "-12");
  481. tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
  482. TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56");
  483. TestFormatSpecifier(tp, tz, "%::z", "+12:00:56");
  484. TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56");
  485. tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
  486. TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56");
  487. TestFormatSpecifier(tp, tz, "%::z", "-12:00:56");
  488. TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56");
  489. tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
  490. TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00");
  491. TestFormatSpecifier(tp, tz, "%::z", "+12:34:00");
  492. TestFormatSpecifier(tp, tz, "%:::z", "+12:34");
  493. tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
  494. TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00");
  495. TestFormatSpecifier(tp, tz, "%::z", "-12:34:00");
  496. TestFormatSpecifier(tp, tz, "%:::z", "-12:34");
  497. tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
  498. chrono::seconds(56));
  499. TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56");
  500. TestFormatSpecifier(tp, tz, "%::z", "+12:34:56");
  501. TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56");
  502. tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
  503. chrono::seconds(56));
  504. TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56");
  505. TestFormatSpecifier(tp, tz, "%::z", "-12:34:56");
  506. TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56");
  507. }
  508. TEST(Format, ExtendedYears) {
  509. const time_zone utc = utc_time_zone();
  510. const char e4y_fmt[] = "%E4Y%m%d"; // no separators
  511. // %E4Y zero-pads the year to produce at least 4 chars, including the sign.
  512. auto tp = convert(civil_second(-999, 11, 27, 0, 0, 0), utc);
  513. EXPECT_EQ("-9991127", cctz::format(e4y_fmt, tp, utc));
  514. tp = convert(civil_second(-99, 11, 27, 0, 0, 0), utc);
  515. EXPECT_EQ("-0991127", cctz::format(e4y_fmt, tp, utc));
  516. tp = convert(civil_second(-9, 11, 27, 0, 0, 0), utc);
  517. EXPECT_EQ("-0091127", cctz::format(e4y_fmt, tp, utc));
  518. tp = convert(civil_second(-1, 11, 27, 0, 0, 0), utc);
  519. EXPECT_EQ("-0011127", cctz::format(e4y_fmt, tp, utc));
  520. tp = convert(civil_second(0, 11, 27, 0, 0, 0), utc);
  521. EXPECT_EQ("00001127", cctz::format(e4y_fmt, tp, utc));
  522. tp = convert(civil_second(1, 11, 27, 0, 0, 0), utc);
  523. EXPECT_EQ("00011127", cctz::format(e4y_fmt, tp, utc));
  524. tp = convert(civil_second(9, 11, 27, 0, 0, 0), utc);
  525. EXPECT_EQ("00091127", cctz::format(e4y_fmt, tp, utc));
  526. tp = convert(civil_second(99, 11, 27, 0, 0, 0), utc);
  527. EXPECT_EQ("00991127", cctz::format(e4y_fmt, tp, utc));
  528. tp = convert(civil_second(999, 11, 27, 0, 0, 0), utc);
  529. EXPECT_EQ("09991127", cctz::format(e4y_fmt, tp, utc));
  530. tp = convert(civil_second(9999, 11, 27, 0, 0, 0), utc);
  531. EXPECT_EQ("99991127", cctz::format(e4y_fmt, tp, utc));
  532. // When the year is outside [-999:9999], more than 4 chars are produced.
  533. tp = convert(civil_second(-1000, 11, 27, 0, 0, 0), utc);
  534. EXPECT_EQ("-10001127", cctz::format(e4y_fmt, tp, utc));
  535. tp = convert(civil_second(10000, 11, 27, 0, 0, 0), utc);
  536. EXPECT_EQ("100001127", cctz::format(e4y_fmt, tp, utc));
  537. }
  538. TEST(Format, RFC3339Format) {
  539. time_zone tz;
  540. EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
  541. time_point<chrono::nanoseconds> tp =
  542. convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
  543. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_full, tp, tz));
  544. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  545. tp += chrono::milliseconds(100);
  546. EXPECT_EQ("1977-06-28T09:08:07.1-07:00", cctz::format(RFC3339_full, tp, tz));
  547. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  548. tp += chrono::milliseconds(20);
  549. EXPECT_EQ("1977-06-28T09:08:07.12-07:00", cctz::format(RFC3339_full, tp, tz));
  550. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  551. tp += chrono::milliseconds(3);
  552. EXPECT_EQ("1977-06-28T09:08:07.123-07:00", cctz::format(RFC3339_full, tp, tz));
  553. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  554. tp += chrono::microseconds(400);
  555. EXPECT_EQ("1977-06-28T09:08:07.1234-07:00", cctz::format(RFC3339_full, tp, tz));
  556. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  557. tp += chrono::microseconds(50);
  558. EXPECT_EQ("1977-06-28T09:08:07.12345-07:00", cctz::format(RFC3339_full, tp, tz));
  559. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  560. tp += chrono::microseconds(6);
  561. EXPECT_EQ("1977-06-28T09:08:07.123456-07:00", cctz::format(RFC3339_full, tp, tz));
  562. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  563. tp += chrono::nanoseconds(700);
  564. EXPECT_EQ("1977-06-28T09:08:07.1234567-07:00", cctz::format(RFC3339_full, tp, tz));
  565. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  566. tp += chrono::nanoseconds(80);
  567. EXPECT_EQ("1977-06-28T09:08:07.12345678-07:00", cctz::format(RFC3339_full, tp, tz));
  568. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  569. tp += chrono::nanoseconds(9);
  570. EXPECT_EQ("1977-06-28T09:08:07.123456789-07:00",
  571. cctz::format(RFC3339_full, tp, tz));
  572. EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz));
  573. }
  574. TEST(Format, RFC1123Format) { // locale specific
  575. time_zone tz;
  576. EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
  577. auto tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
  578. EXPECT_EQ("Tue, 28 Jun 1977 09:08:07 -0700", cctz::format(RFC1123_full, tp, tz));
  579. EXPECT_EQ("28 Jun 1977 09:08:07 -0700", cctz::format(RFC1123_no_wday, tp, tz));
  580. }
  581. TEST(Format, Week) {
  582. const time_zone utc = utc_time_zone();
  583. auto tp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);
  584. EXPECT_EQ("2017-01-7", cctz::format("%Y-%U-%u", tp, utc));
  585. EXPECT_EQ("2017-00-0", cctz::format("%Y-%W-%w", tp, utc));
  586. tp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);
  587. EXPECT_EQ("2017-53-7", cctz::format("%Y-%U-%u", tp, utc));
  588. EXPECT_EQ("2017-52-0", cctz::format("%Y-%W-%w", tp, utc));
  589. tp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);
  590. EXPECT_EQ("2018-00-1", cctz::format("%Y-%U-%u", tp, utc));
  591. EXPECT_EQ("2018-01-1", cctz::format("%Y-%W-%w", tp, utc));
  592. tp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);
  593. EXPECT_EQ("2018-52-1", cctz::format("%Y-%U-%u", tp, utc));
  594. EXPECT_EQ("2018-53-1", cctz::format("%Y-%W-%w", tp, utc));
  595. tp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);
  596. EXPECT_EQ("2019-00-2", cctz::format("%Y-%U-%u", tp, utc));
  597. EXPECT_EQ("2019-00-2", cctz::format("%Y-%W-%w", tp, utc));
  598. tp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
  599. EXPECT_EQ("2019-52-2", cctz::format("%Y-%U-%u", tp, utc));
  600. EXPECT_EQ("2019-52-2", cctz::format("%Y-%W-%w", tp, utc));
  601. }
  602. //
  603. // Testing parse()
  604. //
  605. TEST(Parse, TimePointResolution) {
  606. const char kFmt[] = "%H:%M:%E*S";
  607. const time_zone utc = utc_time_zone();
  608. time_point<chrono::nanoseconds> tp_ns;
  609. EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_ns));
  610. EXPECT_EQ("03:04:05.123456789", cctz::format(kFmt, tp_ns, utc));
  611. EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ns));
  612. EXPECT_EQ("03:04:05.123456", cctz::format(kFmt, tp_ns, utc));
  613. time_point<chrono::microseconds> tp_us;
  614. EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_us));
  615. EXPECT_EQ("03:04:05.123456", cctz::format(kFmt, tp_us, utc));
  616. EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_us));
  617. EXPECT_EQ("03:04:05.123456", cctz::format(kFmt, tp_us, utc));
  618. EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_us));
  619. EXPECT_EQ("03:04:05.123", cctz::format(kFmt, tp_us, utc));
  620. time_point<chrono::milliseconds> tp_ms;
  621. EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ms));
  622. EXPECT_EQ("03:04:05.123", cctz::format(kFmt, tp_ms, utc));
  623. EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_ms));
  624. EXPECT_EQ("03:04:05.123", cctz::format(kFmt, tp_ms, utc));
  625. EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_ms));
  626. EXPECT_EQ("03:04:05", cctz::format(kFmt, tp_ms, utc));
  627. time_point<chrono::seconds> tp_s;
  628. EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_s));
  629. EXPECT_EQ("03:04:05", cctz::format(kFmt, tp_s, utc));
  630. EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_s));
  631. EXPECT_EQ("03:04:05", cctz::format(kFmt, tp_s, utc));
  632. time_point<chrono::minutes> tp_m;
  633. EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_m));
  634. EXPECT_EQ("03:04:00", cctz::format(kFmt, tp_m, utc));
  635. time_point<chrono::hours> tp_h;
  636. EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_h));
  637. EXPECT_EQ("03:00:00", cctz::format(kFmt, tp_h, utc));
  638. }
  639. TEST(Parse, TimePointExtendedResolution) {
  640. const char kFmt[] = "%H:%M:%E*S";
  641. const time_zone utc = utc_time_zone();
  642. time_point<cctz::seconds> tp;
  643. detail::femtoseconds fs;
  644. EXPECT_TRUE(detail::parse(kFmt, "12:34:56.123456789012345", utc, &tp, &fs));
  645. EXPECT_EQ("12:34:56.123456789012345", detail::format(kFmt, tp, fs, utc));
  646. EXPECT_TRUE(detail::parse(kFmt, "12:34:56.012345678901234", utc, &tp, &fs));
  647. EXPECT_EQ("12:34:56.012345678901234", detail::format(kFmt, tp, fs, utc));
  648. EXPECT_TRUE(detail::parse(kFmt, "12:34:56.001234567890123", utc, &tp, &fs));
  649. EXPECT_EQ("12:34:56.001234567890123", detail::format(kFmt, tp, fs, utc));
  650. EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000123", utc, &tp, &fs));
  651. EXPECT_EQ("12:34:56.000000000000123", detail::format(kFmt, tp, fs, utc));
  652. EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000012", utc, &tp, &fs));
  653. EXPECT_EQ("12:34:56.000000000000012", detail::format(kFmt, tp, fs, utc));
  654. EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000001", utc, &tp, &fs));
  655. EXPECT_EQ("12:34:56.000000000000001", detail::format(kFmt, tp, fs, utc));
  656. }
  657. TEST(Parse, Basics) {
  658. time_zone tz = utc_time_zone();
  659. time_point<chrono::nanoseconds> tp =
  660. chrono::system_clock::from_time_t(1234567890);
  661. // Simple edge cases.
  662. EXPECT_TRUE(parse("", "", tz, &tp));
  663. EXPECT_EQ(chrono::system_clock::from_time_t(0), tp); // everything defaulted
  664. EXPECT_TRUE(parse(" ", " ", tz, &tp));
  665. EXPECT_TRUE(parse(" ", " ", tz, &tp));
  666. EXPECT_TRUE(parse("x", "x", tz, &tp));
  667. EXPECT_TRUE(parse("xxx", "xxx", tz, &tp));
  668. EXPECT_TRUE(
  669. parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 -0800", tz, &tp));
  670. ExpectTime(tp, tz, 2013, 6, 29, 3, 8, 9, 0, false, "UTC");
  671. }
  672. TEST(Parse, WithTimeZone) {
  673. time_zone tz;
  674. EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
  675. time_point<chrono::nanoseconds> tp;
  676. // We can parse a string without a UTC offset if we supply a timezone.
  677. EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &tp));
  678. ExpectTime(tp, tz, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true, "PDT");
  679. // But the timezone is ignored when a UTC offset is present.
  680. EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 +0800",
  681. utc_time_zone(), &tp));
  682. ExpectTime(tp, tz, 2013, 6, 28, 19 - 8 - 7, 8, 9, -7 * 60 * 60, true, "PDT");
  683. // Check a skipped time (a Spring DST transition). parse() uses the
  684. // pre-transition offset.
  685. EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-03-13 02:15:00", tz, &tp));
  686. ExpectTime(tp, tz, 2011, 3, 13, 3, 15, 0, -7 * 60 * 60, true, "PDT");
  687. // Check a repeated time (a Fall DST transition). parse() uses the
  688. // pre-transition offset.
  689. EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-11-06 01:15:00", tz, &tp));
  690. ExpectTime(tp, tz, 2011, 11, 6, 1, 15, 0, -7 * 60 * 60, true, "PDT");
  691. }
  692. TEST(Parse, LeapSecond) {
  693. time_zone tz;
  694. EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
  695. time_point<chrono::nanoseconds> tp;
  696. // ":59" -> ":59"
  697. EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59-08:00", tz, &tp));
  698. ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT");
  699. // ":59.5" -> ":59.5"
  700. EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59.5-08:00", tz, &tp));
  701. ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT");
  702. // ":60" -> ":00"
  703. EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60-08:00", tz, &tp));
  704. ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT");
  705. // ":60.5" -> ":00.0"
  706. EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60.5-08:00", tz, &tp));
  707. ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT");
  708. // ":61" -> error
  709. EXPECT_FALSE(parse(RFC3339_full, "2013-06-28T07:08:61-08:00", tz, &tp));
  710. }
  711. TEST(Parse, ErrorCases) {
  712. const time_zone tz = utc_time_zone();
  713. auto tp = chrono::system_clock::from_time_t(0);
  714. // Illegal trailing data.
  715. EXPECT_FALSE(parse("%S", "123", tz, &tp));
  716. // Can't parse an illegal format specifier.
  717. EXPECT_FALSE(parse("%Q", "x", tz, &tp));
  718. // Fails because of trailing, unparsed data "blah".
  719. EXPECT_FALSE(parse("%m-%d", "2-3 blah", tz, &tp));
  720. // Trailing whitespace is allowed.
  721. EXPECT_TRUE(parse("%m-%d", "2-3 ", tz, &tp));
  722. EXPECT_EQ(2, convert(tp, utc_time_zone()).month());
  723. EXPECT_EQ(3, convert(tp, utc_time_zone()).day());
  724. // Feb 31 requires normalization.
  725. EXPECT_FALSE(parse("%m-%d", "2-31", tz, &tp));
  726. // Check that we cannot have spaces in UTC offsets.
  727. EXPECT_TRUE(parse("%z", "-0203", tz, &tp));
  728. EXPECT_FALSE(parse("%z", "- 2 3", tz, &tp));
  729. EXPECT_TRUE(parse("%Ez", "-02:03", tz, &tp));
  730. EXPECT_FALSE(parse("%Ez", "- 2: 3", tz, &tp));
  731. // Check that we reject other malformed UTC offsets.
  732. EXPECT_FALSE(parse("%Ez", "+-08:00", tz, &tp));
  733. EXPECT_FALSE(parse("%Ez", "-+08:00", tz, &tp));
  734. // Check that we do not accept "-0" in fields that allow zero.
  735. EXPECT_FALSE(parse("%Y", "-0", tz, &tp));
  736. EXPECT_FALSE(parse("%E4Y", "-0", tz, &tp));
  737. EXPECT_FALSE(parse("%H", "-0", tz, &tp));
  738. EXPECT_FALSE(parse("%M", "-0", tz, &tp));
  739. EXPECT_FALSE(parse("%S", "-0", tz, &tp));
  740. EXPECT_FALSE(parse("%z", "+-000", tz, &tp));
  741. EXPECT_FALSE(parse("%Ez", "+-0:00", tz, &tp));
  742. EXPECT_FALSE(parse("%z", "-00-0", tz, &tp));
  743. EXPECT_FALSE(parse("%Ez", "-00:-0", tz, &tp));
  744. }
  745. TEST(Parse, PosixConversions) {
  746. time_zone tz = utc_time_zone();
  747. auto tp = chrono::system_clock::from_time_t(0);
  748. const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
  749. tp = reset;
  750. EXPECT_TRUE(parse("%d", "15", tz, &tp));
  751. EXPECT_EQ(15, convert(tp, tz).day());
  752. // %e is an extension, but is supported internally.
  753. tp = reset;
  754. EXPECT_TRUE(parse("%e", "15", tz, &tp));
  755. EXPECT_EQ(15, convert(tp, tz).day()); // Equivalent to %d
  756. tp = reset;
  757. EXPECT_TRUE(parse("%H", "17", tz, &tp));
  758. EXPECT_EQ(17, convert(tp, tz).hour());
  759. tp = reset;
  760. EXPECT_TRUE(parse("%I", "5", tz, &tp));
  761. EXPECT_EQ(5, convert(tp, tz).hour());
  762. // %j is parsed but ignored.
  763. EXPECT_TRUE(parse("%j", "32", tz, &tp));
  764. tp = reset;
  765. EXPECT_TRUE(parse("%m", "11", tz, &tp));
  766. EXPECT_EQ(11, convert(tp, tz).month());
  767. tp = reset;
  768. EXPECT_TRUE(parse("%M", "33", tz, &tp));
  769. EXPECT_EQ(33, convert(tp, tz).minute());
  770. tp = reset;
  771. EXPECT_TRUE(parse("%S", "55", tz, &tp));
  772. EXPECT_EQ(55, convert(tp, tz).second());
  773. // %U is parsed but ignored.
  774. EXPECT_TRUE(parse("%U", "15", tz, &tp));
  775. // %w is parsed but ignored.
  776. EXPECT_TRUE(parse("%w", "2", tz, &tp));
  777. // %W is parsed but ignored.
  778. EXPECT_TRUE(parse("%W", "22", tz, &tp));
  779. tp = reset;
  780. EXPECT_TRUE(parse("%y", "04", tz, &tp));
  781. EXPECT_EQ(2004, convert(tp, tz).year());
  782. tp = reset;
  783. EXPECT_TRUE(parse("%Y", "2004", tz, &tp));
  784. EXPECT_EQ(2004, convert(tp, tz).year());
  785. EXPECT_TRUE(parse("%%", "%", tz, &tp));
  786. #if defined(__linux__)
  787. // SU/C99/TZ extensions
  788. // Because we handle each (non-internal) specifier in a separate call
  789. // to strptime(), there is no way to group %C and %y together. So we
  790. // just skip the %C/%y case.
  791. #if 0
  792. tp = reset;
  793. EXPECT_TRUE(parse("%C %y", "20 04", tz, &tp));
  794. EXPECT_EQ(2004, convert(tp, tz).year());
  795. #endif
  796. tp = reset;
  797. EXPECT_TRUE(parse("%D", "02/03/04", tz, &tp));
  798. EXPECT_EQ(2, convert(tp, tz).month());
  799. EXPECT_EQ(3, convert(tp, tz).day());
  800. EXPECT_EQ(2004, convert(tp, tz).year());
  801. EXPECT_TRUE(parse("%n", "\n", tz, &tp));
  802. tp = reset;
  803. EXPECT_TRUE(parse("%R", "03:44", tz, &tp));
  804. EXPECT_EQ(3, convert(tp, tz).hour());
  805. EXPECT_EQ(44, convert(tp, tz).minute());
  806. EXPECT_TRUE(parse("%t", "\t\v\f\n\r ", tz, &tp));
  807. tp = reset;
  808. EXPECT_TRUE(parse("%T", "03:44:55", tz, &tp));
  809. EXPECT_EQ(3, convert(tp, tz).hour());
  810. EXPECT_EQ(44, convert(tp, tz).minute());
  811. EXPECT_EQ(55, convert(tp, tz).second());
  812. tp = reset;
  813. EXPECT_TRUE(parse("%s", "1234567890", tz, &tp));
  814. EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);
  815. // %s conversion, like %z/%Ez, pays no heed to the optional zone.
  816. time_zone lax;
  817. EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax));
  818. tp = reset;
  819. EXPECT_TRUE(parse("%s", "1234567890", lax, &tp));
  820. EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);
  821. // This is most important when the time has the same YMDhms
  822. // breakdown in the zone as some other time. For example, ...
  823. // 1414917000 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PDT)
  824. // 1414920600 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PST)
  825. tp = reset;
  826. EXPECT_TRUE(parse("%s", "1414917000", lax, &tp));
  827. EXPECT_EQ(chrono::system_clock::from_time_t(1414917000), tp);
  828. tp = reset;
  829. EXPECT_TRUE(parse("%s", "1414920600", lax, &tp));
  830. EXPECT_EQ(chrono::system_clock::from_time_t(1414920600), tp);
  831. #endif
  832. }
  833. TEST(Parse, LocaleSpecific) {
  834. time_zone tz = utc_time_zone();
  835. auto tp = chrono::system_clock::from_time_t(0);
  836. const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
  837. // %a is parsed but ignored.
  838. EXPECT_TRUE(parse("%a", "Mon", tz, &tp));
  839. // %A is parsed but ignored.
  840. EXPECT_TRUE(parse("%A", "Monday", tz, &tp));
  841. tp = reset;
  842. EXPECT_TRUE(parse("%b", "Feb", tz, &tp));
  843. EXPECT_EQ(2, convert(tp, tz).month());
  844. tp = reset;
  845. EXPECT_TRUE(parse("%B", "February", tz, &tp));
  846. EXPECT_EQ(2, convert(tp, tz).month());
  847. // %p is parsed but ignored if it's alone. But it's used with %I.
  848. EXPECT_TRUE(parse("%p", "AM", tz, &tp));
  849. tp = reset;
  850. EXPECT_TRUE(parse("%I %p", "5 PM", tz, &tp));
  851. EXPECT_EQ(17, convert(tp, tz).hour());
  852. tp = reset;
  853. EXPECT_TRUE(parse("%x", "02/03/04", tz, &tp));
  854. if (convert(tp, tz).month() == 2) {
  855. EXPECT_EQ(3, convert(tp, tz).day());
  856. } else {
  857. EXPECT_EQ(2, convert(tp, tz).day());
  858. EXPECT_EQ(3, convert(tp, tz).month());
  859. }
  860. EXPECT_EQ(2004, convert(tp, tz).year());
  861. tp = reset;
  862. EXPECT_TRUE(parse("%X", "15:44:55", tz, &tp));
  863. EXPECT_EQ(15, convert(tp, tz).hour());
  864. EXPECT_EQ(44, convert(tp, tz).minute());
  865. EXPECT_EQ(55, convert(tp, tz).second());
  866. #if defined(__linux__)
  867. // SU/C99/TZ extensions
  868. tp = reset;
  869. EXPECT_TRUE(parse("%h", "Feb", tz, &tp));
  870. EXPECT_EQ(2, convert(tp, tz).month()); // Equivalent to %b
  871. tp = reset;
  872. EXPECT_TRUE(parse("%l %p", "5 PM", tz, &tp));
  873. EXPECT_EQ(17, convert(tp, tz).hour());
  874. tp = reset;
  875. EXPECT_TRUE(parse("%r", "03:44:55 PM", tz, &tp));
  876. EXPECT_EQ(15, convert(tp, tz).hour());
  877. EXPECT_EQ(44, convert(tp, tz).minute());
  878. EXPECT_EQ(55, convert(tp, tz).second());
  879. tp = reset;
  880. EXPECT_TRUE(parse("%Ec", "Tue Nov 19 05:06:07 2013", tz, &tp));
  881. EXPECT_EQ(convert(civil_second(2013, 11, 19, 5, 6, 7), tz), tp);
  882. // Modified conversion specifiers %E_
  883. tp = reset;
  884. EXPECT_TRUE(parse("%Ex", "02/03/04", tz, &tp));
  885. EXPECT_EQ(2, convert(tp, tz).month());
  886. EXPECT_EQ(3, convert(tp, tz).day());
  887. EXPECT_EQ(2004, convert(tp, tz).year());
  888. tp = reset;
  889. EXPECT_TRUE(parse("%EX", "15:44:55", tz, &tp));
  890. EXPECT_EQ(15, convert(tp, tz).hour());
  891. EXPECT_EQ(44, convert(tp, tz).minute());
  892. EXPECT_EQ(55, convert(tp, tz).second());
  893. // %Ey, the year offset from %EC, doesn't really make sense alone as there
  894. // is no way to represent it in tm_year (%EC is not simply the century).
  895. // Yet, because we handle each (non-internal) specifier in a separate call
  896. // to strptime(), there is no way to group %EC and %Ey either. So we just
  897. // skip the %EC and %Ey cases.
  898. tp = reset;
  899. EXPECT_TRUE(parse("%EY", "2004", tz, &tp));
  900. EXPECT_EQ(2004, convert(tp, tz).year());
  901. // Modified conversion specifiers %O_
  902. tp = reset;
  903. EXPECT_TRUE(parse("%Od", "15", tz, &tp));
  904. EXPECT_EQ(15, convert(tp, tz).day());
  905. tp = reset;
  906. EXPECT_TRUE(parse("%Oe", "15", tz, &tp));
  907. EXPECT_EQ(15, convert(tp, tz).day()); // Equivalent to %d
  908. tp = reset;
  909. EXPECT_TRUE(parse("%OH", "17", tz, &tp));
  910. EXPECT_EQ(17, convert(tp, tz).hour());
  911. tp = reset;
  912. EXPECT_TRUE(parse("%OI", "5", tz, &tp));
  913. EXPECT_EQ(5, convert(tp, tz).hour());
  914. tp = reset;
  915. EXPECT_TRUE(parse("%Om", "11", tz, &tp));
  916. EXPECT_EQ(11, convert(tp, tz).month());
  917. tp = reset;
  918. EXPECT_TRUE(parse("%OM", "33", tz, &tp));
  919. EXPECT_EQ(33, convert(tp, tz).minute());
  920. tp = reset;
  921. EXPECT_TRUE(parse("%OS", "55", tz, &tp));
  922. EXPECT_EQ(55, convert(tp, tz).second());
  923. // %OU is parsed but ignored.
  924. EXPECT_TRUE(parse("%OU", "15", tz, &tp));
  925. // %Ow is parsed but ignored.
  926. EXPECT_TRUE(parse("%Ow", "2", tz, &tp));
  927. // %OW is parsed but ignored.
  928. EXPECT_TRUE(parse("%OW", "22", tz, &tp));
  929. tp = reset;
  930. EXPECT_TRUE(parse("%Oy", "04", tz, &tp));
  931. EXPECT_EQ(2004, convert(tp, tz).year());
  932. #endif
  933. }
  934. TEST(Parse, ExtendedSeconds) {
  935. const time_zone tz = utc_time_zone();
  936. const time_point<chrono::nanoseconds> unix_epoch =
  937. chrono::system_clock::from_time_t(0);
  938. // All %E<prec>S cases are treated the same as %E*S on input.
  939. auto precisions = {"*", "0", "1", "2", "3", "4", "5", "6", "7",
  940. "8", "9", "10", "11", "12", "13", "14", "15"};
  941. for (const std::string& prec : precisions) {
  942. const std::string fmt = "%E" + prec + "S";
  943. SCOPED_TRACE(fmt);
  944. time_point<chrono::nanoseconds> tp = unix_epoch;
  945. EXPECT_TRUE(parse(fmt, "5", tz, &tp));
  946. EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
  947. tp = unix_epoch;
  948. EXPECT_TRUE(parse(fmt, "05", tz, &tp));
  949. EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
  950. tp = unix_epoch;
  951. EXPECT_TRUE(parse(fmt, "05.0", tz, &tp));
  952. EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
  953. tp = unix_epoch;
  954. EXPECT_TRUE(parse(fmt, "05.00", tz, &tp));
  955. EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
  956. tp = unix_epoch;
  957. EXPECT_TRUE(parse(fmt, "05.6", tz, &tp));
  958. EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);
  959. tp = unix_epoch;
  960. EXPECT_TRUE(parse(fmt, "05.60", tz, &tp));
  961. EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);
  962. tp = unix_epoch;
  963. EXPECT_TRUE(parse(fmt, "05.600", tz, &tp));
  964. EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);
  965. tp = unix_epoch;
  966. EXPECT_TRUE(parse(fmt, "05.67", tz, &tp));
  967. EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp);
  968. tp = unix_epoch;
  969. EXPECT_TRUE(parse(fmt, "05.670", tz, &tp));
  970. EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp);
  971. tp = unix_epoch;
  972. EXPECT_TRUE(parse(fmt, "05.678", tz, &tp));
  973. EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(678), tp);
  974. }
  975. // Here is a "%E*S" case we got wrong for a while. The fractional
  976. // part of the first instant is less than 2^31 and was correctly
  977. // parsed, while the second (and any subsecond field >=2^31) failed.
  978. time_point<chrono::nanoseconds> tp = unix_epoch;
  979. EXPECT_TRUE(parse("%E*S", "0.2147483647", tz, &tp));
  980. EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
  981. tp = unix_epoch;
  982. EXPECT_TRUE(parse("%E*S", "0.2147483648", tz, &tp));
  983. EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
  984. // We should also be able to specify long strings of digits far
  985. // beyond the current resolution and have them convert the same way.
  986. tp = unix_epoch;
  987. EXPECT_TRUE(parse(
  988. "%E*S", "0.214748364801234567890123456789012345678901234567890123456789",
  989. tz, &tp));
  990. EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
  991. }
  992. TEST(Parse, ExtendedSecondsScan) {
  993. const time_zone tz = utc_time_zone();
  994. time_point<chrono::nanoseconds> tp;
  995. for (int ms = 0; ms < 1000; ms += 111) {
  996. for (int us = 0; us < 1000; us += 27) {
  997. const int micros = ms * 1000 + us;
  998. for (int ns = 0; ns < 1000; ns += 9) {
  999. const auto expected = chrono::system_clock::from_time_t(0) +
  1000. chrono::nanoseconds(micros * 1000 + ns);
  1001. std::ostringstream oss;
  1002. oss << "0." << std::setfill('0') << std::setw(3);
  1003. oss << ms << std::setw(3) << us << std::setw(3) << ns;
  1004. const std::string input = oss.str();
  1005. EXPECT_TRUE(parse("%E*S", input, tz, &tp));
  1006. EXPECT_EQ(expected, tp) << input;
  1007. }
  1008. }
  1009. }
  1010. }
  1011. TEST(Parse, ExtendedSubeconds) {
  1012. const time_zone tz = utc_time_zone();
  1013. const time_point<chrono::nanoseconds> unix_epoch =
  1014. chrono::system_clock::from_time_t(0);
  1015. // All %E<prec>f cases are treated the same as %E*f on input.
  1016. auto precisions = {"*", "0", "1", "2", "3", "4", "5", "6", "7",
  1017. "8", "9", "10", "11", "12", "13", "14", "15"};
  1018. for (const std::string& prec : precisions) {
  1019. const std::string fmt = "%E" + prec + "f";
  1020. SCOPED_TRACE(fmt);
  1021. time_point<chrono::nanoseconds> tp = unix_epoch - chrono::seconds(1);
  1022. EXPECT_TRUE(parse(fmt, "", tz, &tp));
  1023. EXPECT_EQ(unix_epoch, tp);
  1024. tp = unix_epoch;
  1025. EXPECT_TRUE(parse(fmt, "6", tz, &tp));
  1026. EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);
  1027. tp = unix_epoch;
  1028. EXPECT_TRUE(parse(fmt, "60", tz, &tp));
  1029. EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);
  1030. tp = unix_epoch;
  1031. EXPECT_TRUE(parse(fmt, "600", tz, &tp));
  1032. EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);
  1033. tp = unix_epoch;
  1034. EXPECT_TRUE(parse(fmt, "67", tz, &tp));
  1035. EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp);
  1036. tp = unix_epoch;
  1037. EXPECT_TRUE(parse(fmt, "670", tz, &tp));
  1038. EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp);
  1039. tp = unix_epoch;
  1040. EXPECT_TRUE(parse(fmt, "678", tz, &tp));
  1041. EXPECT_EQ(unix_epoch + chrono::milliseconds(678), tp);
  1042. tp = unix_epoch;
  1043. EXPECT_TRUE(parse(fmt, "6789", tz, &tp));
  1044. EXPECT_EQ(
  1045. unix_epoch + chrono::milliseconds(678) + chrono::microseconds(900), tp);
  1046. }
  1047. // Here is a "%E*f" case we got wrong for a while. The fractional
  1048. // part of the first instant is less than 2^31 and was correctly
  1049. // parsed, while the second (and any subsecond field >=2^31) failed.
  1050. time_point<chrono::nanoseconds> tp = unix_epoch;
  1051. EXPECT_TRUE(parse("%E*f", "2147483647", tz, &tp));
  1052. EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
  1053. tp = unix_epoch;
  1054. EXPECT_TRUE(parse("%E*f", "2147483648", tz, &tp));
  1055. EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
  1056. // We should also be able to specify long strings of digits far
  1057. // beyond the current resolution and have them convert the same way.
  1058. tp = unix_epoch;
  1059. EXPECT_TRUE(parse(
  1060. "%E*f", "214748364801234567890123456789012345678901234567890123456789",
  1061. tz, &tp));
  1062. EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
  1063. }
  1064. TEST(Parse, ExtendedSubecondsScan) {
  1065. time_point<chrono::nanoseconds> tp;
  1066. const time_zone tz = utc_time_zone();
  1067. for (int ms = 0; ms < 1000; ms += 111) {
  1068. for (int us = 0; us < 1000; us += 27) {
  1069. const int micros = ms * 1000 + us;
  1070. for (int ns = 0; ns < 1000; ns += 9) {
  1071. std::ostringstream oss;
  1072. oss << std::setfill('0') << std::setw(3) << ms;
  1073. oss << std::setw(3) << us << std::setw(3) << ns;
  1074. const std::string nanos = oss.str();
  1075. const auto expected = chrono::system_clock::from_time_t(0) +
  1076. chrono::nanoseconds(micros * 1000 + ns);
  1077. for (int ps = 0; ps < 1000; ps += 250) {
  1078. std::ostringstream ps_oss;
  1079. oss << std::setfill('0') << std::setw(3) << ps;
  1080. const std::string input = nanos + ps_oss.str() + "999";
  1081. EXPECT_TRUE(parse("%E*f", input, tz, &tp));
  1082. EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input;
  1083. }
  1084. }
  1085. }
  1086. }
  1087. }
  1088. TEST(Parse, ExtendedOffset) {
  1089. const time_zone utc = utc_time_zone();
  1090. time_point<cctz::seconds> tp;
  1091. EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp));
  1092. EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
  1093. EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp));
  1094. EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
  1095. EXPECT_TRUE(parse("%Ez", "+12:34", utc, &tp));
  1096. EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
  1097. EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp));
  1098. for (auto fmt : {"%Ez", "%z"}) {
  1099. EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
  1100. EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
  1101. EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
  1102. EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
  1103. EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
  1104. EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
  1105. EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
  1106. EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
  1107. EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
  1108. EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
  1109. EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
  1110. EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
  1111. EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
  1112. EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
  1113. }
  1114. }
  1115. TEST(Parse, ExtendedSecondOffset) {
  1116. const time_zone utc = utc_time_zone();
  1117. time_point<cctz::seconds> tp;
  1118. for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) {
  1119. EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp));
  1120. EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
  1121. EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp));
  1122. EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
  1123. EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp));
  1124. EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
  1125. EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp));
  1126. EXPECT_TRUE(parse(fmt, "+000000", utc, &tp));
  1127. EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
  1128. EXPECT_TRUE(parse(fmt, "-123456", utc, &tp));
  1129. EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
  1130. EXPECT_TRUE(parse(fmt, "+123456", utc, &tp));
  1131. EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
  1132. EXPECT_FALSE(parse(fmt, "-12345", utc, &tp));
  1133. EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp));
  1134. EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
  1135. EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp));
  1136. EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
  1137. EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp));
  1138. EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
  1139. EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp));
  1140. EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
  1141. EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
  1142. EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
  1143. EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
  1144. EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
  1145. EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
  1146. EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
  1147. EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
  1148. EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
  1149. EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
  1150. EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
  1151. EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
  1152. EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
  1153. EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
  1154. }
  1155. }
  1156. TEST(Parse, ExtendedYears) {
  1157. const time_zone utc = utc_time_zone();
  1158. const char e4y_fmt[] = "%E4Y%m%d"; // no separators
  1159. time_point<cctz::seconds> tp;
  1160. // %E4Y consumes exactly four chars, including any sign.
  1161. EXPECT_TRUE(parse(e4y_fmt, "-9991127", utc, &tp));
  1162. EXPECT_EQ(convert(civil_second(-999, 11, 27, 0, 0, 0), utc), tp);
  1163. EXPECT_TRUE(parse(e4y_fmt, "-0991127", utc, &tp));
  1164. EXPECT_EQ(convert(civil_second(-99, 11, 27, 0, 0, 0), utc), tp);
  1165. EXPECT_TRUE(parse(e4y_fmt, "-0091127", utc, &tp));
  1166. EXPECT_EQ(convert(civil_second(-9, 11, 27, 0, 0, 0), utc), tp);
  1167. EXPECT_TRUE(parse(e4y_fmt, "-0011127", utc, &tp));
  1168. EXPECT_EQ(convert(civil_second(-1, 11, 27, 0, 0, 0), utc), tp);
  1169. EXPECT_TRUE(parse(e4y_fmt, "00001127", utc, &tp));
  1170. EXPECT_EQ(convert(civil_second(0, 11, 27, 0, 0, 0), utc), tp);
  1171. EXPECT_TRUE(parse(e4y_fmt, "00011127", utc, &tp));
  1172. EXPECT_EQ(convert(civil_second(1, 11, 27, 0, 0, 0), utc), tp);
  1173. EXPECT_TRUE(parse(e4y_fmt, "00091127", utc, &tp));
  1174. EXPECT_EQ(convert(civil_second(9, 11, 27, 0, 0, 0), utc), tp);
  1175. EXPECT_TRUE(parse(e4y_fmt, "00991127", utc, &tp));
  1176. EXPECT_EQ(convert(civil_second(99, 11, 27, 0, 0, 0), utc), tp);
  1177. EXPECT_TRUE(parse(e4y_fmt, "09991127", utc, &tp));
  1178. EXPECT_EQ(convert(civil_second(999, 11, 27, 0, 0, 0), utc), tp);
  1179. EXPECT_TRUE(parse(e4y_fmt, "99991127", utc, &tp));
  1180. EXPECT_EQ(convert(civil_second(9999, 11, 27, 0, 0, 0), utc), tp);
  1181. // When the year is outside [-999:9999], the parse fails.
  1182. EXPECT_FALSE(parse(e4y_fmt, "-10001127", utc, &tp));
  1183. EXPECT_FALSE(parse(e4y_fmt, "100001127", utc, &tp));
  1184. }
  1185. TEST(Parse, RFC3339Format) {
  1186. const time_zone tz = utc_time_zone();
  1187. time_point<chrono::nanoseconds> tp;
  1188. EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00+00:00", tz, &tp));
  1189. ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, "UTC");
  1190. // Check that %ET also accepts "t".
  1191. time_point<chrono::nanoseconds> tp2;
  1192. EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12t20:21:00+00:00", tz, &tp2));
  1193. EXPECT_EQ(tp, tp2);
  1194. // Check that %Ez also accepts "Z" as a synonym for "+00:00".
  1195. time_point<chrono::nanoseconds> tp3;
  1196. EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp3));
  1197. EXPECT_EQ(tp, tp3);
  1198. // Check that %Ez also accepts "z" as a synonym for "+00:00".
  1199. time_point<chrono::nanoseconds> tp4;
  1200. EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00z", tz, &tp4));
  1201. EXPECT_EQ(tp, tp4);
  1202. }
  1203. TEST(Parse, Week) {
  1204. const time_zone utc = utc_time_zone();
  1205. time_point<cctz::seconds> tp;
  1206. auto exp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);
  1207. EXPECT_TRUE(parse("%Y-%U-%u", "2017-01-7", utc, &tp));
  1208. EXPECT_EQ(exp, tp);
  1209. EXPECT_TRUE(parse("%Y-%W-%w", "2017-00-0", utc, &tp));
  1210. EXPECT_EQ(exp, tp);
  1211. exp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);
  1212. EXPECT_TRUE(parse("%Y-%U-%u", "2017-53-7", utc, &tp));
  1213. EXPECT_EQ(exp, tp);
  1214. EXPECT_TRUE(parse("%Y-%W-%w", "2017-52-0", utc, &tp));
  1215. EXPECT_EQ(exp, tp);
  1216. exp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);
  1217. EXPECT_TRUE(parse("%Y-%U-%u", "2018-00-1", utc, &tp));
  1218. EXPECT_EQ(exp, tp);
  1219. EXPECT_TRUE(parse("%Y-%W-%w", "2018-01-1", utc, &tp));
  1220. EXPECT_EQ(exp, tp);
  1221. exp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);
  1222. EXPECT_TRUE(parse("%Y-%U-%u", "2018-52-1", utc, &tp));
  1223. EXPECT_EQ(exp, tp);
  1224. EXPECT_TRUE(parse("%Y-%W-%w", "2018-53-1", utc, &tp));
  1225. EXPECT_EQ(exp, tp);
  1226. exp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);
  1227. EXPECT_TRUE(parse("%Y-%U-%u", "2019-00-2", utc, &tp));
  1228. EXPECT_EQ(exp, tp);
  1229. EXPECT_TRUE(parse("%Y-%W-%w", "2019-00-2", utc, &tp));
  1230. EXPECT_EQ(exp, tp);
  1231. exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
  1232. EXPECT_TRUE(parse("%Y-%U-%u", "2019-52-2", utc, &tp));
  1233. EXPECT_EQ(exp, tp);
  1234. EXPECT_TRUE(parse("%Y-%W-%w", "2019-52-2", utc, &tp));
  1235. EXPECT_EQ(exp, tp);
  1236. }
  1237. TEST(Parse, WeekYearShift) {
  1238. // %U/%W conversions with week values in {0, 52, 53} can slip
  1239. // into the previous/following calendar years.
  1240. const time_zone utc = utc_time_zone();
  1241. time_point<cctz::seconds> tp;
  1242. auto exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
  1243. EXPECT_TRUE(parse("%Y-%U-%u", "2020-00-2", utc, &tp));
  1244. EXPECT_EQ(exp, tp);
  1245. EXPECT_TRUE(parse("%Y-%W-%w", "2020-00-2", utc, &tp));
  1246. EXPECT_EQ(exp, tp);
  1247. exp = convert(civil_second(2021, 1, 1, 0, 0, 0), utc);
  1248. EXPECT_TRUE(parse("%Y-%U-%u", "2020-52-5", utc, &tp));
  1249. EXPECT_EQ(exp, tp);
  1250. EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp));
  1251. EXPECT_EQ(exp, tp);
  1252. // Slipping into the previous/following calendar years should fail when
  1253. // we're already at the extremes.
  1254. EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp));
  1255. EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp));
  1256. }
  1257. TEST(Parse, MaxRange) {
  1258. const time_zone utc = utc_time_zone();
  1259. time_point<cctz::seconds> tp;
  1260. // tests the upper limit using +00:00 offset
  1261. EXPECT_TRUE(
  1262. parse(RFC3339_sec, "292277026596-12-04T15:30:07+00:00", utc, &tp));
  1263. EXPECT_EQ(tp, time_point<cctz::seconds>::max());
  1264. EXPECT_FALSE(
  1265. parse(RFC3339_sec, "292277026596-12-04T15:30:08+00:00", utc, &tp));
  1266. // tests the upper limit using -01:00 offset
  1267. EXPECT_TRUE(
  1268. parse(RFC3339_sec, "292277026596-12-04T14:30:07-01:00", utc, &tp));
  1269. EXPECT_EQ(tp, time_point<cctz::seconds>::max());
  1270. EXPECT_FALSE(
  1271. parse(RFC3339_sec, "292277026596-12-04T15:30:07-01:00", utc, &tp));
  1272. // tests the lower limit using +00:00 offset
  1273. EXPECT_TRUE(
  1274. parse(RFC3339_sec, "-292277022657-01-27T08:29:52+00:00", utc, &tp));
  1275. EXPECT_EQ(tp, time_point<cctz::seconds>::min());
  1276. EXPECT_FALSE(
  1277. parse(RFC3339_sec, "-292277022657-01-27T08:29:51+00:00", utc, &tp));
  1278. // tests the lower limit using +01:00 offset
  1279. EXPECT_TRUE(
  1280. parse(RFC3339_sec, "-292277022657-01-27T09:29:52+01:00", utc, &tp));
  1281. EXPECT_EQ(tp, time_point<cctz::seconds>::min());
  1282. EXPECT_FALSE(
  1283. parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp));
  1284. // tests max/min civil-second overflow
  1285. EXPECT_FALSE(parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01",
  1286. utc, &tp));
  1287. EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01",
  1288. utc, &tp));
  1289. // TODO: Add tests that parsing times with fractional seconds overflow
  1290. // appropriately. This can't be done until cctz::parse() properly detects
  1291. // overflow when combining the chrono seconds and femto.
  1292. }
  1293. //
  1294. // Roundtrip test for format()/parse().
  1295. //
  1296. TEST(FormatParse, RoundTrip) {
  1297. time_zone lax;
  1298. EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax));
  1299. const auto in = convert(civil_second(1977, 6, 28, 9, 8, 7), lax);
  1300. const auto subseconds = chrono::nanoseconds(654321);
  1301. // RFC3339, which renders subseconds.
  1302. {
  1303. time_point<chrono::nanoseconds> out;
  1304. const std::string s = cctz::format(RFC3339_full, in + subseconds, lax);
  1305. EXPECT_TRUE(parse(RFC3339_full, s, lax, &out)) << s;
  1306. EXPECT_EQ(in + subseconds, out); // RFC3339_full includes %Ez
  1307. }
  1308. // RFC1123, which only does whole seconds.
  1309. {
  1310. time_point<chrono::nanoseconds> out;
  1311. const std::string s = cctz::format(RFC1123_full, in, lax);
  1312. EXPECT_TRUE(parse(RFC1123_full, s, lax, &out)) << s;
  1313. EXPECT_EQ(in, out); // RFC1123_full includes %z
  1314. }
  1315. #if defined(_WIN32) || defined(_WIN64)
  1316. // Initial investigations indicate the %c does not roundtrip on Windows.
  1317. // TODO: Figure out what is going on here (perhaps a locale problem).
  1318. #else
  1319. // Even though we don't know what %c will produce, it should roundtrip,
  1320. // but only in the 0-offset timezone.
  1321. {
  1322. time_point<chrono::nanoseconds> out;
  1323. time_zone utc = utc_time_zone();
  1324. const std::string s = cctz::format("%c", in, utc);
  1325. EXPECT_TRUE(parse("%c", s, utc, &out)) << s;
  1326. EXPECT_EQ(in, out);
  1327. }
  1328. #endif
  1329. }
  1330. TEST(FormatParse, RoundTripDistantFuture) {
  1331. const time_zone utc = utc_time_zone();
  1332. const time_point<cctz::seconds> in = time_point<cctz::seconds>::max();
  1333. const std::string s = cctz::format(RFC3339_full, in, utc);
  1334. time_point<cctz::seconds> out;
  1335. EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
  1336. EXPECT_EQ(in, out);
  1337. }
  1338. TEST(FormatParse, RoundTripDistantPast) {
  1339. const time_zone utc = utc_time_zone();
  1340. const time_point<cctz::seconds> in = time_point<cctz::seconds>::min();
  1341. const std::string s = cctz::format(RFC3339_full, in, utc);
  1342. time_point<cctz::seconds> out;
  1343. EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
  1344. EXPECT_EQ(in, out);
  1345. }
  1346. } // namespace cctz