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