1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "utils/jvm-test-utils.h"
18 #include "gtest/gtest.h"
19
20 namespace libtextclassifier3 {
21 namespace {
22
23 class CalendarTest : public ::testing::Test {
24 protected:
CalendarTest()25 CalendarTest()
26 : calendarlib_(libtextclassifier3::CreateCalendarLibForTesting()) {}
27
28 static constexpr int kWednesday = 4;
29 std::unique_ptr<CalendarLib> calendarlib_;
30 };
31
TEST_F(CalendarTest,Interface)32 TEST_F(CalendarTest, Interface) {
33 int64 time;
34 DatetimeGranularity granularity;
35 std::string timezone;
36 DatetimeParsedData data;
37 bool result = calendarlib_->InterpretParseData(
38 data, /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Zurich",
39 /*reference_locale=*/"en-CH",
40 /*prefer_future_for_unspecified_date=*/false, &time, &granularity);
41 TC3_LOG(INFO) << result;
42 }
43
TEST_F(CalendarTest,SetsZeroTimeWhenNotRelative)44 TEST_F(CalendarTest, SetsZeroTimeWhenNotRelative) {
45 int64 time;
46 DatetimeGranularity granularity;
47 DatetimeParsedData data;
48 data.SetAbsoluteValue(DatetimeComponent::ComponentType::YEAR, 2018);
49
50 ASSERT_TRUE(calendarlib_->InterpretParseData(
51 data,
52 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
53 /*reference_locale=*/"en-CH",
54 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
55 EXPECT_EQ(time, 1514761200000L /* Jan 01 2018 00:00:00 */);
56
57 ASSERT_TRUE(calendarlib_->InterpretParseData(
58 data,
59 /*reference_time_ms_utc=*/1L, /*reference_timezone=*/"Europe/Zurich",
60 /*reference_locale=*/"en-CH",
61 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
62 EXPECT_EQ(time, 1514761200000L /* Jan 01 2018 00:00:00 */);
63 }
64
TEST_F(CalendarTest,SetsTimeZone)65 TEST_F(CalendarTest, SetsTimeZone) {
66 int64 time;
67 DatetimeGranularity granularity;
68 DatetimeParsedData data;
69 data.SetAbsoluteValue(DatetimeComponent::ComponentType::YEAR, 2018);
70 data.SetAbsoluteValue(DatetimeComponent::ComponentType::HOUR, 7);
71 data.SetAbsoluteValue(DatetimeComponent::ComponentType::MINUTE, 30);
72 data.SetAbsoluteValue(DatetimeComponent::ComponentType::SECOND, 10);
73
74 ASSERT_TRUE(calendarlib_->InterpretParseData(
75 data,
76 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
77 /*reference_locale=*/"en-CH",
78 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
79 EXPECT_EQ(time, 1514788210000L /* Jan 01 2018 07:30:10 GMT+01:00 */);
80
81 data.SetAbsoluteValue(DatetimeComponent::ComponentType::ZONE_OFFSET,
82 60); // GMT+01:00
83 ASSERT_TRUE(calendarlib_->InterpretParseData(
84 data,
85 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
86 /*reference_locale=*/"en-CH",
87 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
88 EXPECT_EQ(time, 1514788210000L /* Jan 01 2018 07:30:10 GMT+01:00 */);
89
90 // Now the hour is in terms of GMT+02:00 which is one hour ahead of
91 // GMT+01:00.
92 data.SetAbsoluteValue(DatetimeComponent::ComponentType::ZONE_OFFSET,
93 120); // GMT+02:00
94 ASSERT_TRUE(calendarlib_->InterpretParseData(
95 data,
96 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
97 /*reference_locale=*/"en-CH",
98 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
99 EXPECT_EQ(time, 1514784610000L /* Jan 01 2018 06:30:10 GMT+01:00 */);
100 }
101
TEST_F(CalendarTest,RoundingToGranularityBasic)102 TEST_F(CalendarTest, RoundingToGranularityBasic) {
103 int64 time;
104 DatetimeGranularity granularity;
105 DatetimeParsedData data;
106
107 data.SetAbsoluteValue(DatetimeComponent::ComponentType::YEAR, 2018);
108 ASSERT_TRUE(calendarlib_->InterpretParseData(
109 data,
110 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
111 /*reference_locale=*/"en-CH",
112 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
113 EXPECT_EQ(time, 1514761200000L /* Jan 01 2018 00:00:00 */);
114
115 data.SetAbsoluteValue(DatetimeComponent::ComponentType::MONTH, 4);
116 ASSERT_TRUE(calendarlib_->InterpretParseData(
117 data,
118 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
119 /*reference_locale=*/"en-CH",
120 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
121 EXPECT_EQ(time, 1522533600000L /* Apr 01 2018 00:00:00 */);
122
123 data.SetAbsoluteValue(DatetimeComponent::ComponentType::DAY_OF_MONTH, 25);
124 ASSERT_TRUE(calendarlib_->InterpretParseData(
125 data,
126 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
127 /*reference_locale=*/"en-CH",
128 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
129 EXPECT_EQ(time, 1524607200000L /* Apr 25 2018 00:00:00 */);
130
131 data.SetAbsoluteValue(DatetimeComponent::ComponentType::HOUR, 9);
132 ASSERT_TRUE(calendarlib_->InterpretParseData(
133 data,
134 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
135 /*reference_locale=*/"en-CH",
136 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
137 EXPECT_EQ(time, 1524639600000L /* Apr 25 2018 09:00:00 */);
138
139 data.SetAbsoluteValue(DatetimeComponent::ComponentType::MINUTE, 33);
140 ASSERT_TRUE(calendarlib_->InterpretParseData(
141 data,
142 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
143 /*reference_locale=*/"en-CH",
144 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
145 EXPECT_EQ(time, 1524641580000 /* Apr 25 2018 09:33:00 */);
146
147 data.SetAbsoluteValue(DatetimeComponent::ComponentType::SECOND, 59);
148 ASSERT_TRUE(calendarlib_->InterpretParseData(
149 data,
150 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
151 /*reference_locale=*/"en-CH",
152 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
153 EXPECT_EQ(time, 1524641639000 /* Apr 25 2018 09:33:59 */);
154 }
155
TEST_F(CalendarTest,RoundingToGranularityWeek)156 TEST_F(CalendarTest, RoundingToGranularityWeek) {
157 int64 time;
158 DatetimeGranularity granularity;
159 // Prepare data structure that means: "next week"
160 DatetimeParsedData data;
161 data.SetRelativeValue(DatetimeComponent::ComponentType::WEEK,
162 DatetimeComponent::RelativeQualifier::NEXT);
163 data.SetRelativeCount(DatetimeComponent::ComponentType::WEEK, 1);
164
165 ASSERT_TRUE(calendarlib_->InterpretParseData(
166 data,
167 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
168 /*reference_locale=*/"de-CH",
169 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
170 EXPECT_EQ(time, 342000000L /* Mon Jan 05 1970 00:00:00 */);
171
172 ASSERT_TRUE(calendarlib_->InterpretParseData(
173 data,
174 /*reference_time_ms_utc=*/0L, /*reference_timezone=*/"Europe/Zurich",
175 /*reference_locale=*/"en-US",
176 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
177 EXPECT_EQ(time, 255600000L /* Sun Jan 04 1970 00:00:00 */);
178 }
179
TEST_F(CalendarTest,RelativeTime)180 TEST_F(CalendarTest, RelativeTime) {
181 const int64 ref_time = 1524648839000L; /* 25 April 2018 09:33:59 */
182 int64 time;
183 DatetimeGranularity granularity;
184
185 // Two Weds from now.
186 DatetimeParsedData future_wed_parse;
187 future_wed_parse.SetRelativeValue(
188 DatetimeComponent::ComponentType::DAY_OF_WEEK,
189 DatetimeComponent::RelativeQualifier::FUTURE);
190 future_wed_parse.SetRelativeCount(
191 DatetimeComponent::ComponentType::DAY_OF_WEEK, 2);
192 future_wed_parse.SetAbsoluteValue(
193 DatetimeComponent::ComponentType::DAY_OF_WEEK, kWednesday);
194
195 ASSERT_TRUE(calendarlib_->InterpretParseData(
196 future_wed_parse, ref_time, /*reference_timezone=*/"Europe/Zurich",
197 /*reference_locale=*/"en-US",
198 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
199 EXPECT_EQ(time, 1525858439000L /* Wed May 09 2018 11:33:59 */);
200 EXPECT_EQ(granularity, GRANULARITY_DAY);
201
202 // Next Wed.
203 DatetimeParsedData next_wed_parse;
204 next_wed_parse.SetAbsoluteValue(DatetimeComponent::ComponentType::DAY_OF_WEEK,
205 kWednesday);
206 next_wed_parse.SetRelativeValue(DatetimeComponent::ComponentType::DAY_OF_WEEK,
207 DatetimeComponent::RelativeQualifier::NEXT);
208 next_wed_parse.SetRelativeCount(DatetimeComponent::ComponentType::DAY_OF_WEEK,
209 1);
210
211 ASSERT_TRUE(calendarlib_->InterpretParseData(
212 next_wed_parse, ref_time, /*reference_timezone=*/"Europe/Zurich",
213 /*reference_locale=*/"en-US",
214 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
215 EXPECT_EQ(time, 1525212000000L /* Wed May 02 2018 00:00:00 */);
216 EXPECT_EQ(granularity, GRANULARITY_DAY);
217
218 // Same Wed.
219 DatetimeParsedData same_wed_parse;
220 same_wed_parse.SetRelativeValue(DatetimeComponent::ComponentType::DAY_OF_WEEK,
221 DatetimeComponent::RelativeQualifier::THIS);
222 same_wed_parse.SetAbsoluteValue(DatetimeComponent::ComponentType::DAY_OF_WEEK,
223 kWednesday);
224 same_wed_parse.SetRelativeCount(DatetimeComponent::ComponentType::DAY_OF_WEEK,
225 1);
226
227 ASSERT_TRUE(calendarlib_->InterpretParseData(
228 same_wed_parse, ref_time, /*reference_timezone=*/"Europe/Zurich",
229 /*reference_locale=*/"en-US",
230 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
231 EXPECT_EQ(time, 1524607200000L /* Wed Apr 25 2018 00:00:00 */);
232 EXPECT_EQ(granularity, GRANULARITY_DAY);
233
234 // Previous Wed.
235 DatetimeParsedData last_wed_parse;
236 last_wed_parse.SetRelativeValue(DatetimeComponent::ComponentType::DAY_OF_WEEK,
237 DatetimeComponent::RelativeQualifier::LAST);
238 last_wed_parse.SetAbsoluteValue(DatetimeComponent::ComponentType::DAY_OF_WEEK,
239 kWednesday);
240 last_wed_parse.SetRelativeCount(DatetimeComponent::ComponentType::DAY_OF_WEEK,
241 1);
242
243 ASSERT_TRUE(calendarlib_->InterpretParseData(
244 last_wed_parse, ref_time, /*reference_timezone=*/"Europe/Zurich",
245 /*reference_locale=*/"en-US",
246 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
247 EXPECT_EQ(time, 1524002400000L /* Wed Apr 18 2018 00:00:00 */);
248 EXPECT_EQ(granularity, GRANULARITY_DAY);
249
250 // Two Weds ago.
251 DatetimeParsedData past_wed_parse;
252 past_wed_parse.SetRelativeValue(DatetimeComponent::ComponentType::DAY_OF_WEEK,
253 DatetimeComponent::RelativeQualifier::PAST);
254 past_wed_parse.SetAbsoluteValue(DatetimeComponent::ComponentType::DAY_OF_WEEK,
255 kWednesday);
256 past_wed_parse.SetRelativeCount(DatetimeComponent::ComponentType::DAY_OF_WEEK,
257 -2);
258
259 ASSERT_TRUE(calendarlib_->InterpretParseData(
260 past_wed_parse, ref_time, /*reference_timezone=*/"Europe/Zurich",
261 /*reference_locale=*/"en-US",
262 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
263 EXPECT_EQ(time, 1523439239000L /* Wed Apr 11 2018 11:33:59 */);
264 EXPECT_EQ(granularity, GRANULARITY_DAY);
265
266 // In 3 hours.
267 DatetimeParsedData in_3_hours_parse;
268 in_3_hours_parse.SetRelativeValue(
269 DatetimeComponent::ComponentType::HOUR,
270 DatetimeComponent::RelativeQualifier::FUTURE);
271 in_3_hours_parse.SetRelativeCount(DatetimeComponent::ComponentType::HOUR, 3);
272
273 ASSERT_TRUE(calendarlib_->InterpretParseData(
274 in_3_hours_parse, ref_time, /*reference_timezone=*/"Europe/Zurich",
275 /*reference_locale=*/"en-US",
276 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
277 EXPECT_EQ(time, 1524659639000L /* Wed Apr 25 2018 14:33:59 */);
278 EXPECT_EQ(granularity, GRANULARITY_HOUR);
279
280 // In 5 minutes.
281 DatetimeParsedData in_5_minutes_parse;
282 in_5_minutes_parse.SetRelativeValue(
283 DatetimeComponent::ComponentType::MINUTE,
284 DatetimeComponent::RelativeQualifier::FUTURE);
285 in_5_minutes_parse.SetRelativeCount(DatetimeComponent::ComponentType::MINUTE,
286 5);
287
288 ASSERT_TRUE(calendarlib_->InterpretParseData(
289 in_5_minutes_parse, ref_time, /*reference_timezone=*/"Europe/Zurich",
290 /*reference_locale=*/"en-US",
291 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
292 EXPECT_EQ(time, 1524649139000L /* Wed Apr 25 2018 14:33:59 */);
293 EXPECT_EQ(granularity, GRANULARITY_MINUTE);
294
295 // In 10 seconds.
296 DatetimeParsedData in_10_seconds_parse;
297 in_10_seconds_parse.SetRelativeValue(
298 DatetimeComponent::ComponentType::SECOND,
299 DatetimeComponent::RelativeQualifier::FUTURE);
300 in_10_seconds_parse.SetRelativeCount(DatetimeComponent::ComponentType::SECOND,
301 10);
302
303 ASSERT_TRUE(calendarlib_->InterpretParseData(
304 in_10_seconds_parse, ref_time, /*reference_timezone=*/"Europe/Zurich",
305 /*reference_locale=*/"en-US",
306 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
307 EXPECT_EQ(time, 1524648849000L /* Wed Apr 25 2018 14:33:59 */);
308 EXPECT_EQ(granularity, GRANULARITY_SECOND);
309 }
310
TEST_F(CalendarTest,AddsADayWhenTimeInThePastAndDayNotSpecified)311 TEST_F(CalendarTest, AddsADayWhenTimeInThePastAndDayNotSpecified) {
312 int64 time;
313 DatetimeGranularity granularity;
314 DatetimeParsedData data;
315 data.SetAbsoluteValue(DatetimeComponent::ComponentType::HOUR, 7);
316 data.SetAbsoluteValue(DatetimeComponent::ComponentType::MINUTE, 10);
317
318 ASSERT_TRUE(calendarlib_->InterpretParseData(
319 data,
320 /*reference_time_ms_utc=*/1567317600000L /* Sept 01 2019 00:00:00 */,
321 /*reference_timezone=*/"Europe/Zurich",
322 /*reference_locale=*/"en-CH", /*prefer_future_for_unspecified_date=*/true,
323 &time, &granularity));
324 EXPECT_EQ(time, 1567401000000L /* Sept 02 2019 07:10:00 */);
325 }
326
TEST_F(CalendarTest,DoesntAddADayWhenTimeInThePastAndDayNotSpecifiedAndDisabled)327 TEST_F(CalendarTest,
328 DoesntAddADayWhenTimeInThePastAndDayNotSpecifiedAndDisabled) {
329 int64 time;
330 DatetimeGranularity granularity;
331 DatetimeParsedData data;
332 data.SetAbsoluteValue(DatetimeComponent::ComponentType::HOUR, 7);
333 data.SetAbsoluteValue(DatetimeComponent::ComponentType::MINUTE, 10);
334
335 ASSERT_TRUE(calendarlib_->InterpretParseData(
336 data,
337 /*reference_time_ms_utc=*/1567317600000L /* Sept 01 2019 00:00:00 */,
338 /*reference_timezone=*/"Europe/Zurich",
339 /*reference_locale=*/"en-CH",
340 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
341 EXPECT_EQ(time, 1567314600000L /* Sept 01 2019 07:10:00 */);
342 }
343
TEST_F(CalendarTest,DoesntAddADayWhenTimeInTheFutureAndDayNotSpecified)344 TEST_F(CalendarTest, DoesntAddADayWhenTimeInTheFutureAndDayNotSpecified) {
345 int64 time;
346 DatetimeGranularity granularity;
347 DatetimeParsedData data;
348 data.SetAbsoluteValue(DatetimeComponent::ComponentType::HOUR, 9);
349 data.SetAbsoluteValue(DatetimeComponent::ComponentType::MINUTE, 10);
350
351 ASSERT_TRUE(calendarlib_->InterpretParseData(
352 data,
353 /*reference_time_ms_utc=*/1567317600000L /* Sept 01 2019 00:00:00 */,
354 /*reference_timezone=*/"Europe/Zurich",
355 /*reference_locale=*/"en-CH", /*prefer_future_for_unspecified_date=*/true,
356 &time, &granularity));
357 EXPECT_EQ(time, 1567321800000L /* Sept 01 2019 09:10:00 */);
358
359 ASSERT_TRUE(calendarlib_->InterpretParseData(
360 data,
361 /*reference_time_ms_utc=*/1567317600000L /* Sept 01 2019 00:00:00 */,
362 /*reference_timezone=*/"Europe/Zurich",
363 /*reference_locale=*/"en-CH",
364 /*prefer_future_for_unspecified_date=*/false, &time, &granularity));
365 EXPECT_EQ(time, 1567321800000L /* Sept 01 2019 09:10:00 */);
366 }
367
368 } // namespace
369 } // namespace libtextclassifier3
370