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