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