format_test.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. // Copyright 2017 The Abseil Authors.
  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 <cstdint>
  15. #include <limits>
  16. #include <string>
  17. #include "gmock/gmock.h"
  18. #include "gtest/gtest.h"
  19. #include "absl/time/internal/test_util.h"
  20. #include "absl/time/time.h"
  21. using testing::HasSubstr;
  22. namespace {
  23. // A helper that tests the given format specifier by itself, and with leading
  24. // and trailing characters. For example: TestFormatSpecifier(t, "%a", "Thu").
  25. void TestFormatSpecifier(absl::Time t, absl::TimeZone tz,
  26. const std::string& fmt, const std::string& ans) {
  27. EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz));
  28. EXPECT_EQ("xxx " + ans, absl::FormatTime("xxx " + fmt, t, tz));
  29. EXPECT_EQ(ans + " yyy", absl::FormatTime(fmt + " yyy", t, tz));
  30. EXPECT_EQ("xxx " + ans + " yyy",
  31. absl::FormatTime("xxx " + fmt + " yyy", t, tz));
  32. }
  33. //
  34. // Testing FormatTime()
  35. //
  36. TEST(FormatTime, Basics) {
  37. absl::TimeZone tz = absl::UTCTimeZone();
  38. absl::Time t = absl::FromTimeT(0);
  39. // Starts with a couple basic edge cases.
  40. EXPECT_EQ("", absl::FormatTime("", t, tz));
  41. EXPECT_EQ(" ", absl::FormatTime(" ", t, tz));
  42. EXPECT_EQ(" ", absl::FormatTime(" ", t, tz));
  43. EXPECT_EQ("xxx", absl::FormatTime("xxx", t, tz));
  44. std::string big(128, 'x');
  45. EXPECT_EQ(big, absl::FormatTime(big, t, tz));
  46. // Cause the 1024-byte buffer to grow.
  47. std::string bigger(100000, 'x');
  48. EXPECT_EQ(bigger, absl::FormatTime(bigger, t, tz));
  49. t += absl::Hours(13) + absl::Minutes(4) + absl::Seconds(5);
  50. t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
  51. EXPECT_EQ("1970-01-01", absl::FormatTime("%Y-%m-%d", t, tz));
  52. EXPECT_EQ("13:04:05", absl::FormatTime("%H:%M:%S", t, tz));
  53. EXPECT_EQ("13:04:05.006", absl::FormatTime("%H:%M:%E3S", t, tz));
  54. EXPECT_EQ("13:04:05.006007", absl::FormatTime("%H:%M:%E6S", t, tz));
  55. EXPECT_EQ("13:04:05.006007008", absl::FormatTime("%H:%M:%E9S", t, tz));
  56. }
  57. TEST(FormatTime, LocaleSpecific) {
  58. const absl::TimeZone tz = absl::UTCTimeZone();
  59. absl::Time t = absl::FromTimeT(0);
  60. TestFormatSpecifier(t, tz, "%a", "Thu");
  61. TestFormatSpecifier(t, tz, "%A", "Thursday");
  62. TestFormatSpecifier(t, tz, "%b", "Jan");
  63. TestFormatSpecifier(t, tz, "%B", "January");
  64. // %c should at least produce the numeric year and time-of-day.
  65. const std::string s =
  66. absl::FormatTime("%c", absl::FromTimeT(0), absl::UTCTimeZone());
  67. EXPECT_THAT(s, HasSubstr("1970"));
  68. EXPECT_THAT(s, HasSubstr("00:00:00"));
  69. TestFormatSpecifier(t, tz, "%p", "AM");
  70. TestFormatSpecifier(t, tz, "%x", "01/01/70");
  71. TestFormatSpecifier(t, tz, "%X", "00:00:00");
  72. }
  73. TEST(FormatTime, ExtendedSeconds) {
  74. const absl::TimeZone tz = absl::UTCTimeZone();
  75. // No subseconds.
  76. absl::Time t = absl::FromTimeT(0) + absl::Seconds(5);
  77. EXPECT_EQ("05", absl::FormatTime("%E*S", t, tz));
  78. EXPECT_EQ("05.000000000000000", absl::FormatTime("%E15S", t, tz));
  79. // With subseconds.
  80. t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
  81. EXPECT_EQ("05.006007008", absl::FormatTime("%E*S", t, tz));
  82. EXPECT_EQ("05", absl::FormatTime("%E0S", t, tz));
  83. EXPECT_EQ("05.006007008000000", absl::FormatTime("%E15S", t, tz));
  84. // Times before the Unix epoch.
  85. t = absl::FromUnixMicros(-1);
  86. EXPECT_EQ("1969-12-31 23:59:59.999999",
  87. absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
  88. // Here is a "%E*S" case we got wrong for a while. While the first
  89. // instant below is correctly rendered as "...:07.333304", the second
  90. // one used to appear as "...:07.33330499999999999".
  91. t = absl::FromUnixMicros(1395024427333304);
  92. EXPECT_EQ("2014-03-17 02:47:07.333304",
  93. absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
  94. t += absl::Microseconds(1);
  95. EXPECT_EQ("2014-03-17 02:47:07.333305",
  96. absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
  97. }
  98. TEST(FormatTime, RFC1123FormatPadsYear) { // locale specific
  99. absl::TimeZone tz = absl::UTCTimeZone();
  100. // A year of 77 should be padded to 0077.
  101. absl::Time t = absl::FromCivil(absl::CivilSecond(77, 6, 28, 9, 8, 7), tz);
  102. EXPECT_EQ("Mon, 28 Jun 0077 09:08:07 +0000",
  103. absl::FormatTime(absl::RFC1123_full, t, tz));
  104. EXPECT_EQ("28 Jun 0077 09:08:07 +0000",
  105. absl::FormatTime(absl::RFC1123_no_wday, t, tz));
  106. }
  107. TEST(FormatTime, InfiniteTime) {
  108. absl::TimeZone tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
  109. // The format and timezone are ignored.
  110. EXPECT_EQ("infinite-future",
  111. absl::FormatTime("%H:%M blah", absl::InfiniteFuture(), tz));
  112. EXPECT_EQ("infinite-past",
  113. absl::FormatTime("%H:%M blah", absl::InfinitePast(), tz));
  114. }
  115. //
  116. // Testing ParseTime()
  117. //
  118. TEST(ParseTime, Basics) {
  119. absl::Time t = absl::FromTimeT(1234567890);
  120. std::string err;
  121. // Simple edge cases.
  122. EXPECT_TRUE(absl::ParseTime("", "", &t, &err)) << err;
  123. EXPECT_EQ(absl::UnixEpoch(), t); // everything defaulted
  124. EXPECT_TRUE(absl::ParseTime(" ", " ", &t, &err)) << err;
  125. EXPECT_TRUE(absl::ParseTime(" ", " ", &t, &err)) << err;
  126. EXPECT_TRUE(absl::ParseTime("x", "x", &t, &err)) << err;
  127. EXPECT_TRUE(absl::ParseTime("xxx", "xxx", &t, &err)) << err;
  128. EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
  129. "2013-06-28 19:08:09 -0800", &t, &err))
  130. << err;
  131. const auto ci = absl::FixedTimeZone(-8 * 60 * 60).At(t);
  132. EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
  133. EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
  134. }
  135. TEST(ParseTime, NullErrorString) {
  136. absl::Time t;
  137. EXPECT_FALSE(absl::ParseTime("%Q", "invalid format", &t, nullptr));
  138. EXPECT_FALSE(absl::ParseTime("%H", "12 trailing data", &t, nullptr));
  139. EXPECT_FALSE(
  140. absl::ParseTime("%H out of range", "42 out of range", &t, nullptr));
  141. }
  142. TEST(ParseTime, WithTimeZone) {
  143. const absl::TimeZone tz =
  144. absl::time_internal::LoadTimeZone("America/Los_Angeles");
  145. absl::Time t;
  146. std::string e;
  147. // We can parse a string without a UTC offset if we supply a timezone.
  148. EXPECT_TRUE(
  149. absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
  150. << e;
  151. auto ci = tz.At(t);
  152. EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
  153. EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
  154. // But the timezone is ignored when a UTC offset is present.
  155. EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
  156. "2013-06-28 19:08:09 +0800", tz, &t, &e))
  157. << e;
  158. ci = absl::FixedTimeZone(8 * 60 * 60).At(t);
  159. EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
  160. EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
  161. }
  162. TEST(ParseTime, ErrorCases) {
  163. absl::Time t = absl::FromTimeT(0);
  164. std::string err;
  165. EXPECT_FALSE(absl::ParseTime("%S", "123", &t, &err)) << err;
  166. EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
  167. // Can't parse an illegal format specifier.
  168. err.clear();
  169. EXPECT_FALSE(absl::ParseTime("%Q", "x", &t, &err)) << err;
  170. // Exact contents of "err" are platform-dependent because of
  171. // differences in the strptime implementation between macOS and Linux.
  172. EXPECT_FALSE(err.empty());
  173. // Fails because of trailing, unparsed data "blah".
  174. EXPECT_FALSE(absl::ParseTime("%m-%d", "2-3 blah", &t, &err)) << err;
  175. EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
  176. // Feb 31 requires normalization.
  177. EXPECT_FALSE(absl::ParseTime("%m-%d", "2-31", &t, &err)) << err;
  178. EXPECT_THAT(err, HasSubstr("Out-of-range"));
  179. // Check that we cannot have spaces in UTC offsets.
  180. EXPECT_TRUE(absl::ParseTime("%z", "-0203", &t, &err)) << err;
  181. EXPECT_FALSE(absl::ParseTime("%z", "- 2 3", &t, &err)) << err;
  182. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  183. EXPECT_TRUE(absl::ParseTime("%Ez", "-02:03", &t, &err)) << err;
  184. EXPECT_FALSE(absl::ParseTime("%Ez", "- 2: 3", &t, &err)) << err;
  185. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  186. // Check that we reject other malformed UTC offsets.
  187. EXPECT_FALSE(absl::ParseTime("%Ez", "+-08:00", &t, &err)) << err;
  188. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  189. EXPECT_FALSE(absl::ParseTime("%Ez", "-+08:00", &t, &err)) << err;
  190. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  191. // Check that we do not accept "-0" in fields that allow zero.
  192. EXPECT_FALSE(absl::ParseTime("%Y", "-0", &t, &err)) << err;
  193. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  194. EXPECT_FALSE(absl::ParseTime("%E4Y", "-0", &t, &err)) << err;
  195. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  196. EXPECT_FALSE(absl::ParseTime("%H", "-0", &t, &err)) << err;
  197. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  198. EXPECT_FALSE(absl::ParseTime("%M", "-0", &t, &err)) << err;
  199. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  200. EXPECT_FALSE(absl::ParseTime("%S", "-0", &t, &err)) << err;
  201. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  202. EXPECT_FALSE(absl::ParseTime("%z", "+-000", &t, &err)) << err;
  203. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  204. EXPECT_FALSE(absl::ParseTime("%Ez", "+-0:00", &t, &err)) << err;
  205. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  206. EXPECT_FALSE(absl::ParseTime("%z", "-00-0", &t, &err)) << err;
  207. EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
  208. EXPECT_FALSE(absl::ParseTime("%Ez", "-00:-0", &t, &err)) << err;
  209. EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
  210. }
  211. TEST(ParseTime, ExtendedSeconds) {
  212. std::string err;
  213. absl::Time t;
  214. // Here is a "%E*S" case we got wrong for a while. The fractional
  215. // part of the first instant is less than 2^31 and was correctly
  216. // parsed, while the second (and any subsecond field >=2^31) failed.
  217. t = absl::UnixEpoch();
  218. EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483647", &t, &err)) << err;
  219. EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
  220. absl::Nanoseconds(1) / 2,
  221. t);
  222. t = absl::UnixEpoch();
  223. EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483648", &t, &err)) << err;
  224. EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
  225. absl::Nanoseconds(3) / 4,
  226. t);
  227. // We should also be able to specify long strings of digits far
  228. // beyond the current resolution and have them convert the same way.
  229. t = absl::UnixEpoch();
  230. EXPECT_TRUE(absl::ParseTime(
  231. "%E*S", "0.214748364801234567890123456789012345678901234567890123456789",
  232. &t, &err))
  233. << err;
  234. EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
  235. absl::Nanoseconds(3) / 4,
  236. t);
  237. }
  238. TEST(ParseTime, ExtendedOffsetErrors) {
  239. std::string err;
  240. absl::Time t;
  241. // %z against +-HHMM.
  242. EXPECT_FALSE(absl::ParseTime("%z", "-123", &t, &err)) << err;
  243. EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
  244. // %z against +-HH.
  245. EXPECT_FALSE(absl::ParseTime("%z", "-1", &t, &err)) << err;
  246. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  247. // %Ez against +-HH:MM.
  248. EXPECT_FALSE(absl::ParseTime("%Ez", "-12:3", &t, &err)) << err;
  249. EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
  250. // %Ez against +-HHMM.
  251. EXPECT_FALSE(absl::ParseTime("%Ez", "-123", &t, &err)) << err;
  252. EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
  253. // %Ez against +-HH.
  254. EXPECT_FALSE(absl::ParseTime("%Ez", "-1", &t, &err)) << err;
  255. EXPECT_THAT(err, HasSubstr("Failed to parse"));
  256. }
  257. TEST(ParseTime, InfiniteTime) {
  258. absl::Time t;
  259. std::string err;
  260. EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future", &t, &err));
  261. EXPECT_EQ(absl::InfiniteFuture(), t);
  262. // Surrounding whitespace.
  263. EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-future", &t, &err));
  264. EXPECT_EQ(absl::InfiniteFuture(), t);
  265. EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future ", &t, &err));
  266. EXPECT_EQ(absl::InfiniteFuture(), t);
  267. EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-future ", &t, &err));
  268. EXPECT_EQ(absl::InfiniteFuture(), t);
  269. EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past", &t, &err));
  270. EXPECT_EQ(absl::InfinitePast(), t);
  271. // Surrounding whitespace.
  272. EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-past", &t, &err));
  273. EXPECT_EQ(absl::InfinitePast(), t);
  274. EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past ", &t, &err));
  275. EXPECT_EQ(absl::InfinitePast(), t);
  276. EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-past ", &t, &err));
  277. EXPECT_EQ(absl::InfinitePast(), t);
  278. // "infinite-future" as literal string
  279. absl::TimeZone tz = absl::UTCTimeZone();
  280. EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04",
  281. &t, &err));
  282. EXPECT_NE(absl::InfiniteFuture(), t);
  283. EXPECT_EQ(3, tz.At(t).cs.hour());
  284. EXPECT_EQ(4, tz.At(t).cs.minute());
  285. // "infinite-past" as literal string
  286. EXPECT_TRUE(
  287. absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
  288. EXPECT_NE(absl::InfinitePast(), t);
  289. EXPECT_EQ(3, tz.At(t).cs.hour());
  290. EXPECT_EQ(4, tz.At(t).cs.minute());
  291. // The input doesn't match the format.
  292. EXPECT_FALSE(absl::ParseTime("infinite-future %H:%M", "03:04", &t, &err));
  293. EXPECT_FALSE(absl::ParseTime("infinite-past %H:%M", "03:04", &t, &err));
  294. }
  295. TEST(ParseTime, FailsOnUnrepresentableTime) {
  296. const absl::TimeZone utc = absl::UTCTimeZone();
  297. absl::Time t;
  298. EXPECT_FALSE(
  299. absl::ParseTime("%Y-%m-%d", "-292277022657-01-27", utc, &t, nullptr));
  300. EXPECT_TRUE(
  301. absl::ParseTime("%Y-%m-%d", "-292277022657-01-28", utc, &t, nullptr));
  302. EXPECT_TRUE(
  303. absl::ParseTime("%Y-%m-%d", "292277026596-12-04", utc, &t, nullptr));
  304. EXPECT_FALSE(
  305. absl::ParseTime("%Y-%m-%d", "292277026596-12-05", utc, &t, nullptr));
  306. }
  307. //
  308. // Roundtrip test for FormatTime()/ParseTime().
  309. //
  310. TEST(FormatParse, RoundTrip) {
  311. const absl::TimeZone lax =
  312. absl::time_internal::LoadTimeZone("America/Los_Angeles");
  313. const absl::Time in =
  314. absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax);
  315. const absl::Duration subseconds = absl::Nanoseconds(654321);
  316. std::string err;
  317. // RFC3339, which renders subseconds.
  318. {
  319. absl::Time out;
  320. const std::string s =
  321. absl::FormatTime(absl::RFC3339_full, in + subseconds, lax);
  322. EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
  323. << s << ": " << err;
  324. EXPECT_EQ(in + subseconds, out); // RFC3339_full includes %Ez
  325. }
  326. // RFC1123, which only does whole seconds.
  327. {
  328. absl::Time out;
  329. const std::string s = absl::FormatTime(absl::RFC1123_full, in, lax);
  330. EXPECT_TRUE(absl::ParseTime(absl::RFC1123_full, s, &out, &err))
  331. << s << ": " << err;
  332. EXPECT_EQ(in, out); // RFC1123_full includes %z
  333. }
  334. // `absl::FormatTime()` falls back to strftime() for "%c", which appears to
  335. // work. On Windows, `absl::ParseTime()` falls back to std::get_time() which
  336. // appears to fail on "%c" (or at least on the "%c" text produced by
  337. // `strftime()`). This makes it fail the round-trip test.
  338. //
  339. // Under the emscripten compiler `absl::ParseTime() falls back to
  340. // `strptime()`, but that ends up using a different definition for "%c"
  341. // compared to `strftime()`, also causing the round-trip test to fail
  342. // (see https://github.com/kripken/emscripten/pull/7491).
  343. #if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
  344. // Even though we don't know what %c will produce, it should roundtrip,
  345. // but only in the 0-offset timezone.
  346. {
  347. absl::Time out;
  348. const std::string s = absl::FormatTime("%c", in, absl::UTCTimeZone());
  349. EXPECT_TRUE(absl::ParseTime("%c", s, &out, &err)) << s << ": " << err;
  350. EXPECT_EQ(in, out);
  351. }
  352. #endif // !_MSC_VER && !__EMSCRIPTEN__
  353. }
  354. TEST(FormatParse, RoundTripDistantFuture) {
  355. const absl::TimeZone tz = absl::UTCTimeZone();
  356. const absl::Time in =
  357. absl::FromUnixSeconds(std::numeric_limits<int64_t>::max());
  358. std::string err;
  359. absl::Time out;
  360. const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
  361. EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
  362. << s << ": " << err;
  363. EXPECT_EQ(in, out);
  364. }
  365. TEST(FormatParse, RoundTripDistantPast) {
  366. const absl::TimeZone tz = absl::UTCTimeZone();
  367. const absl::Time in =
  368. absl::FromUnixSeconds(std::numeric_limits<int64_t>::min());
  369. std::string err;
  370. absl::Time out;
  371. const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
  372. EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
  373. << s << ": " << err;
  374. EXPECT_EQ(in, out);
  375. }
  376. } // namespace