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 "annotator/datetime/grammar-parser.h"
18
19 #include <memory>
20 #include <string>
21
22 #include "annotator/datetime/datetime-grounder.h"
23 #include "annotator/datetime/testing/base-parser-test.h"
24 #include "annotator/datetime/testing/datetime-component-builder.h"
25 #include "annotator/model_generated.h"
26 #include "utils/grammar/analyzer.h"
27 #include "utils/jvm-test-utils.h"
28 #include "utils/test-data-test-utils.h"
29 #include "gmock/gmock.h"
30 #include "gtest/gtest.h"
31
32 using ::libtextclassifier3::grammar::Analyzer;
33 using ::libtextclassifier3::grammar::RulesSet;
34
35 namespace libtextclassifier3 {
36 namespace {
GetModelPath()37 std::string GetModelPath() { return GetTestDataPath("annotator/test_data/"); }
38
ReadFile(const std::string & file_name)39 std::string ReadFile(const std::string& file_name) {
40 std::ifstream file_stream(file_name);
41 return std::string(std::istreambuf_iterator<char>(file_stream), {});
42 }
43
44 class GrammarDatetimeParserTest : public DateTimeParserTest {
45 public:
SetUp()46 void SetUp() override { ResetParser(ModeFlag_ALL); }
47
48 // Exposes the date time parser for tests and evaluations.
DatetimeParserForTests() const49 const DatetimeParser* DatetimeParserForTests() const override {
50 return parser_.get();
51 }
52
53 protected:
ResetParser(ModeFlag enabled_modes)54 void ResetParser(ModeFlag enabled_modes) {
55 grammar_buffer_ = ReadFile(GetModelPath() + "datetime.fb");
56 unilib_ = CreateUniLibForTesting();
57 calendarlib_ = CreateCalendarLibForTesting();
58 analyzer_ = std::make_unique<Analyzer>(
59 unilib_.get(), flatbuffers::GetRoot<RulesSet>(grammar_buffer_.data()));
60 datetime_grounder_ = std::make_unique<DatetimeGrounder>(calendarlib_.get());
61 parser_.reset(new GrammarDatetimeParser(*analyzer_, *datetime_grounder_,
62 /*target_classification_score=*/1.0,
63 /*priority_score=*/1.0,
64 enabled_modes));
65 }
66
67 private:
68 std::string grammar_buffer_;
69 std::unique_ptr<UniLib> unilib_;
70 std::unique_ptr<CalendarLib> calendarlib_;
71 std::unique_ptr<Analyzer> analyzer_;
72 std::unique_ptr<DatetimeGrounder> datetime_grounder_;
73 std::unique_ptr<DatetimeParser> parser_;
74 };
75
TEST_F(GrammarDatetimeParserTest,ParseShort)76 TEST_F(GrammarDatetimeParserTest, ParseShort) {
77 EXPECT_TRUE(ParsesCorrectly(
78 "{01/02/2020}", 1580511600000, GRANULARITY_DAY,
79 {DatetimeComponentsBuilder()
80 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
81 .Add(DatetimeComponent::ComponentType::MONTH, 2)
82 .Add(DatetimeComponent::ComponentType::YEAR, 2020)
83 .Build()},
84 /*anchor_start_end=*/false,
85 /*timezone=*/"Europe/Zurich",
86 /*locales=*/"en-GB"));
87
88 EXPECT_TRUE(ParsesCorrectly(
89 "{01/02/2020}", 1577919600000, GRANULARITY_DAY,
90 {DatetimeComponentsBuilder()
91 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 2)
92 .Add(DatetimeComponent::ComponentType::MONTH, 1)
93 .Add(DatetimeComponent::ComponentType::YEAR, 2020)
94 .Build()}));
95
96 EXPECT_TRUE(ParsesCorrectly(
97 "{January 1, 1988}", 567990000000, GRANULARITY_DAY,
98 {DatetimeComponentsBuilder()
99 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
100 .Add(DatetimeComponent::ComponentType::MONTH, 1)
101 .Add(DatetimeComponent::ComponentType::YEAR, 1988)
102 .Build()}));
103 }
104
TEST_F(GrammarDatetimeParserTest,Parse)105 TEST_F(GrammarDatetimeParserTest, Parse) {
106 EXPECT_TRUE(ParsesCorrectly(
107 "{January 1, 1988}", 567990000000, GRANULARITY_DAY,
108 {DatetimeComponentsBuilder()
109 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
110 .Add(DatetimeComponent::ComponentType::MONTH, 1)
111 .Add(DatetimeComponent::ComponentType::YEAR, 1988)
112 .Build()}));
113 EXPECT_TRUE(ParsesCorrectly(
114 "{january 31 2018}", 1517353200000, GRANULARITY_DAY,
115 {DatetimeComponentsBuilder()
116 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 31)
117 .Add(DatetimeComponent::ComponentType::MONTH, 1)
118 .Add(DatetimeComponent::ComponentType::YEAR, 2018)
119 .Build()}));
120 EXPECT_TRUE(ParsesCorrectly(
121 "foo {1 january 2018} bar", 1514761200000, GRANULARITY_DAY,
122 {DatetimeComponentsBuilder()
123 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
124 .Add(DatetimeComponent::ComponentType::MONTH, 1)
125 .Add(DatetimeComponent::ComponentType::YEAR, 2018)
126 .Build()}));
127 EXPECT_TRUE(ParsesCorrectly(
128 "{09/Mar/2004 22:02:40}", 1078866160000, GRANULARITY_SECOND,
129 {DatetimeComponentsBuilder()
130 .Add(DatetimeComponent::ComponentType::SECOND, 40)
131 .Add(DatetimeComponent::ComponentType::MINUTE, 02)
132 .Add(DatetimeComponent::ComponentType::HOUR, 22)
133 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 9)
134 .Add(DatetimeComponent::ComponentType::MONTH, 3)
135 .Add(DatetimeComponent::ComponentType::YEAR, 2004)
136 .Build()}));
137 EXPECT_TRUE(ParsesCorrectly(
138 "{Dec 2, 2010 2:39:58 AM}", 1291253998000, GRANULARITY_SECOND,
139 {DatetimeComponentsBuilder()
140 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
141 .Add(DatetimeComponent::ComponentType::SECOND, 58)
142 .Add(DatetimeComponent::ComponentType::MINUTE, 39)
143 .Add(DatetimeComponent::ComponentType::HOUR, 2)
144 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 2)
145 .Add(DatetimeComponent::ComponentType::MONTH, 12)
146 .Add(DatetimeComponent::ComponentType::YEAR, 2010)
147 .Build()}));
148 EXPECT_TRUE(ParsesCorrectly(
149 "{Jun 09 2011 15:28:14}", 1307626094000, GRANULARITY_SECOND,
150 {DatetimeComponentsBuilder()
151 .Add(DatetimeComponent::ComponentType::SECOND, 14)
152 .Add(DatetimeComponent::ComponentType::MINUTE, 28)
153 .Add(DatetimeComponent::ComponentType::HOUR, 15)
154 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 9)
155 .Add(DatetimeComponent::ComponentType::MONTH, 6)
156 .Add(DatetimeComponent::ComponentType::YEAR, 2011)
157 .Build()}));
158 EXPECT_TRUE(ParsesCorrectly(
159 "{2010-06-26 02:31:29}", {1277512289000, 1277555489000},
160 GRANULARITY_SECOND,
161 {DatetimeComponentsBuilder()
162 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
163 .Add(DatetimeComponent::ComponentType::SECOND, 29)
164 .Add(DatetimeComponent::ComponentType::MINUTE, 31)
165 .Add(DatetimeComponent::ComponentType::HOUR, 2)
166 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 26)
167 .Add(DatetimeComponent::ComponentType::MONTH, 6)
168 .Add(DatetimeComponent::ComponentType::YEAR, 2010)
169 .Build(),
170 DatetimeComponentsBuilder()
171 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
172 .Add(DatetimeComponent::ComponentType::SECOND, 29)
173 .Add(DatetimeComponent::ComponentType::MINUTE, 31)
174 .Add(DatetimeComponent::ComponentType::HOUR, 2)
175 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 26)
176 .Add(DatetimeComponent::ComponentType::MONTH, 6)
177 .Add(DatetimeComponent::ComponentType::YEAR, 2010)
178 .Build()}));
179 EXPECT_TRUE(ParsesCorrectly(
180 "{2006/01/22 04:11:05}", {1137899465000, 1137942665000},
181 GRANULARITY_SECOND,
182 {DatetimeComponentsBuilder()
183 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
184 .Add(DatetimeComponent::ComponentType::SECOND, 5)
185 .Add(DatetimeComponent::ComponentType::MINUTE, 11)
186 .Add(DatetimeComponent::ComponentType::HOUR, 4)
187 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 22)
188 .Add(DatetimeComponent::ComponentType::MONTH, 1)
189 .Add(DatetimeComponent::ComponentType::YEAR, 2006)
190 .Build(),
191 DatetimeComponentsBuilder()
192 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
193 .Add(DatetimeComponent::ComponentType::SECOND, 5)
194 .Add(DatetimeComponent::ComponentType::MINUTE, 11)
195 .Add(DatetimeComponent::ComponentType::HOUR, 4)
196 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 22)
197 .Add(DatetimeComponent::ComponentType::MONTH, 1)
198 .Add(DatetimeComponent::ComponentType::YEAR, 2006)
199 .Build()}));
200 EXPECT_TRUE(
201 ParsesCorrectly("{11:42:35}", {38555000, 81755000}, GRANULARITY_SECOND,
202 {DatetimeComponentsBuilder()
203 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
204 .Add(DatetimeComponent::ComponentType::SECOND, 35)
205 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
206 .Add(DatetimeComponent::ComponentType::HOUR, 11)
207 .Build(),
208 DatetimeComponentsBuilder()
209 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
210 .Add(DatetimeComponent::ComponentType::SECOND, 35)
211 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
212 .Add(DatetimeComponent::ComponentType::HOUR, 11)
213 .Build()}));
214 EXPECT_TRUE(ParsesCorrectly(
215 "{23/Apr 11:42:35}", {9715355000, 9758555000}, GRANULARITY_SECOND,
216 {DatetimeComponentsBuilder()
217 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
218 .Add(DatetimeComponent::ComponentType::SECOND, 35)
219 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
220 .Add(DatetimeComponent::ComponentType::HOUR, 11)
221 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
222 .Add(DatetimeComponent::ComponentType::MONTH, 4)
223 .Build(),
224 DatetimeComponentsBuilder()
225 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
226 .Add(DatetimeComponent::ComponentType::SECOND, 35)
227 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
228 .Add(DatetimeComponent::ComponentType::HOUR, 11)
229 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
230 .Add(DatetimeComponent::ComponentType::MONTH, 4)
231 .Build()}));
232 EXPECT_TRUE(ParsesCorrectly(
233 "{23/Apr/2015 11:42:35}", {1429782155000, 1429825355000},
234 GRANULARITY_SECOND,
235 {DatetimeComponentsBuilder()
236 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
237 .Add(DatetimeComponent::ComponentType::SECOND, 35)
238 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
239 .Add(DatetimeComponent::ComponentType::HOUR, 11)
240 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
241 .Add(DatetimeComponent::ComponentType::MONTH, 4)
242 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
243 .Build(),
244 DatetimeComponentsBuilder()
245 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
246 .Add(DatetimeComponent::ComponentType::SECOND, 35)
247 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
248 .Add(DatetimeComponent::ComponentType::HOUR, 11)
249 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
250 .Add(DatetimeComponent::ComponentType::MONTH, 4)
251 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
252 .Build()}));
253 EXPECT_TRUE(ParsesCorrectly(
254 "{23-Apr-2015 11:42:35}", {1429782155000, 1429825355000},
255 GRANULARITY_SECOND,
256 {DatetimeComponentsBuilder()
257 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
258 .Add(DatetimeComponent::ComponentType::SECOND, 35)
259 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
260 .Add(DatetimeComponent::ComponentType::HOUR, 11)
261 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
262 .Add(DatetimeComponent::ComponentType::MONTH, 4)
263 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
264 .Build(),
265 DatetimeComponentsBuilder()
266 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
267 .Add(DatetimeComponent::ComponentType::SECOND, 35)
268 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
269 .Add(DatetimeComponent::ComponentType::HOUR, 11)
270 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
271 .Add(DatetimeComponent::ComponentType::MONTH, 4)
272 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
273 .Build()}));
274 EXPECT_TRUE(ParsesCorrectly(
275 "{23 Apr 2015 11:42:35}", {1429782155000, 1429825355000},
276 GRANULARITY_SECOND,
277 {DatetimeComponentsBuilder()
278 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
279 .Add(DatetimeComponent::ComponentType::SECOND, 35)
280 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
281 .Add(DatetimeComponent::ComponentType::HOUR, 11)
282 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
283 .Add(DatetimeComponent::ComponentType::MONTH, 4)
284 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
285 .Build(),
286 DatetimeComponentsBuilder()
287 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
288 .Add(DatetimeComponent::ComponentType::SECOND, 35)
289 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
290 .Add(DatetimeComponent::ComponentType::HOUR, 11)
291 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
292 .Add(DatetimeComponent::ComponentType::MONTH, 4)
293 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
294 .Build()}));
295 EXPECT_TRUE(ParsesCorrectly(
296 "Are sentiments apartments decisively the especially alteration. "
297 "Thrown shy denote ten ladies though ask saw. Or by to he going "
298 "think order event music. Incommode so intention defective at "
299 "convinced. Led income months itself and houses you. After nor "
300 "you leave might share court balls. {19/apr/2010 06:36:15} Are "
301 "sentiments apartments decisively the especially alteration. "
302 "Thrown shy denote ten ladies though ask saw. Or by to he going "
303 "think order event music. Incommode so intention defective at "
304 "convinced. Led income months itself and houses you. After nor "
305 "you leave might share court balls. ",
306 {1271651775000, 1271694975000}, GRANULARITY_SECOND,
307 {DatetimeComponentsBuilder()
308 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
309 .Add(DatetimeComponent::ComponentType::SECOND, 15)
310 .Add(DatetimeComponent::ComponentType::MINUTE, 36)
311 .Add(DatetimeComponent::ComponentType::HOUR, 6)
312 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19)
313 .Add(DatetimeComponent::ComponentType::MONTH, 4)
314 .Add(DatetimeComponent::ComponentType::YEAR, 2010)
315 .Build(),
316 DatetimeComponentsBuilder()
317 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
318 .Add(DatetimeComponent::ComponentType::SECOND, 15)
319 .Add(DatetimeComponent::ComponentType::MINUTE, 36)
320 .Add(DatetimeComponent::ComponentType::HOUR, 6)
321 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19)
322 .Add(DatetimeComponent::ComponentType::MONTH, 4)
323 .Add(DatetimeComponent::ComponentType::YEAR, 2010)
324 .Build()}));
325
326 EXPECT_TRUE(ParsesCorrectly(
327 "{january 1 2018 at 4:30}", {1514777400000, 1514820600000},
328 GRANULARITY_MINUTE,
329 {DatetimeComponentsBuilder()
330 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
331 .Add(DatetimeComponent::ComponentType::MINUTE, 30)
332 .Add(DatetimeComponent::ComponentType::HOUR, 4)
333 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
334 .Add(DatetimeComponent::ComponentType::MONTH, 1)
335 .Add(DatetimeComponent::ComponentType::YEAR, 2018)
336 .Build(),
337 DatetimeComponentsBuilder()
338 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
339 .Add(DatetimeComponent::ComponentType::MINUTE, 30)
340 .Add(DatetimeComponent::ComponentType::HOUR, 4)
341 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
342 .Add(DatetimeComponent::ComponentType::MONTH, 1)
343 .Add(DatetimeComponent::ComponentType::YEAR, 2018)
344 .Build()}));
345 EXPECT_TRUE(ParsesCorrectly(
346 "{january 1 2018 at 4:30 am}", 1514777400000, GRANULARITY_MINUTE,
347 {DatetimeComponentsBuilder()
348 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
349 .Add(DatetimeComponent::ComponentType::MINUTE, 30)
350 .Add(DatetimeComponent::ComponentType::HOUR, 4)
351 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
352 .Add(DatetimeComponent::ComponentType::MONTH, 1)
353 .Add(DatetimeComponent::ComponentType::YEAR, 2018)
354 .Build()}));
355 EXPECT_TRUE(ParsesCorrectly(
356 "{january 1 2018 at 4pm}", 1514818800000, GRANULARITY_HOUR,
357 {DatetimeComponentsBuilder()
358 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
359 .Add(DatetimeComponent::ComponentType::HOUR, 4)
360 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
361 .Add(DatetimeComponent::ComponentType::MONTH, 1)
362 .Add(DatetimeComponent::ComponentType::YEAR, 2018)
363 .Build()}));
364
365 EXPECT_TRUE(ParsesCorrectly(
366 "{today at 0:00}", {-3600000, 39600000}, GRANULARITY_MINUTE,
367 {DatetimeComponentsBuilder()
368 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
369 .Add(DatetimeComponent::ComponentType::MINUTE, 0)
370 .Add(DatetimeComponent::ComponentType::HOUR, 0)
371 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
372 DatetimeComponent::RelativeQualifier::NOW, 0)
373 .Build(),
374 DatetimeComponentsBuilder()
375 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
376 .Add(DatetimeComponent::ComponentType::MINUTE, 0)
377 .Add(DatetimeComponent::ComponentType::HOUR, 0)
378 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
379 DatetimeComponent::RelativeQualifier::NOW, 0)
380 .Build()}));
381 EXPECT_TRUE(ParsesCorrectly(
382 "{today at 0:00}", {-57600000, -14400000}, GRANULARITY_MINUTE,
383 {DatetimeComponentsBuilder()
384 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
385 .Add(DatetimeComponent::ComponentType::MINUTE, 0)
386 .Add(DatetimeComponent::ComponentType::HOUR, 0)
387 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
388 DatetimeComponent::RelativeQualifier::NOW, 0)
389 .Build(),
390 DatetimeComponentsBuilder()
391 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
392 .Add(DatetimeComponent::ComponentType::MINUTE, 0)
393 .Add(DatetimeComponent::ComponentType::HOUR, 0)
394 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
395 DatetimeComponent::RelativeQualifier::NOW, 0)
396 .Build()},
397 /*anchor_start_end=*/false, "America/Los_Angeles"));
398 EXPECT_TRUE(ParsesCorrectly(
399 "{tomorrow at 4:00}", {97200000, 140400000}, GRANULARITY_MINUTE,
400 {DatetimeComponentsBuilder()
401 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
402 .Add(DatetimeComponent::ComponentType::MINUTE, 0)
403 .Add(DatetimeComponent::ComponentType::HOUR, 4)
404 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
405 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
406 .Build(),
407 DatetimeComponentsBuilder()
408 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
409 .Add(DatetimeComponent::ComponentType::MINUTE, 0)
410 .Add(DatetimeComponent::ComponentType::HOUR, 4)
411 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
412 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
413 .Build()}));
414 EXPECT_TRUE(ParsesCorrectly(
415 "{tomorrow at 4am}", 97200000, GRANULARITY_HOUR,
416 {DatetimeComponentsBuilder()
417 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
418 .Add(DatetimeComponent::ComponentType::HOUR, 4)
419 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
420 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
421 .Build()}));
422 EXPECT_TRUE(ParsesCorrectly(
423 "last seen {today at 9:01 PM}", 72060000, GRANULARITY_MINUTE,
424 {DatetimeComponentsBuilder()
425 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
426 .Add(DatetimeComponent::ComponentType::MINUTE, 1)
427 .Add(DatetimeComponent::ComponentType::HOUR, 9)
428 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
429 DatetimeComponent::RelativeQualifier::NOW, 0)
430 .Build()}));
431 EXPECT_TRUE(
432 ParsesCorrectly("set an alarm for {7 a.m}", 21600000, GRANULARITY_HOUR,
433 {DatetimeComponentsBuilder()
434 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
435 .Add(DatetimeComponent::ComponentType::HOUR, 7)
436 .Build()}));
437
438 EXPECT_TRUE(ParsesCorrectly(
439 "{04/23/15 11:42:35}", {1429782155000, 1429825355000}, GRANULARITY_SECOND,
440 {DatetimeComponentsBuilder()
441 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
442 .Add(DatetimeComponent::ComponentType::SECOND, 35)
443 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
444 .Add(DatetimeComponent::ComponentType::HOUR, 11)
445 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
446 .Add(DatetimeComponent::ComponentType::MONTH, 4)
447 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
448 .Build(),
449 DatetimeComponentsBuilder()
450 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
451 .Add(DatetimeComponent::ComponentType::SECOND, 35)
452 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
453 .Add(DatetimeComponent::ComponentType::HOUR, 11)
454 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
455 .Add(DatetimeComponent::ComponentType::MONTH, 4)
456 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
457 .Build()}));
458
459 EXPECT_TRUE(ParsesCorrectly(
460 "{04/23/2015 11:42:35}", {1429782155000, 1429825355000},
461 GRANULARITY_SECOND,
462 {DatetimeComponentsBuilder()
463 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
464 .Add(DatetimeComponent::ComponentType::SECOND, 35)
465 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
466 .Add(DatetimeComponent::ComponentType::HOUR, 11)
467 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
468 .Add(DatetimeComponent::ComponentType::MONTH, 4)
469 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
470 .Build(),
471 DatetimeComponentsBuilder()
472 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
473 .Add(DatetimeComponent::ComponentType::SECOND, 35)
474 .Add(DatetimeComponent::ComponentType::MINUTE, 42)
475 .Add(DatetimeComponent::ComponentType::HOUR, 11)
476 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
477 .Add(DatetimeComponent::ComponentType::MONTH, 4)
478 .Add(DatetimeComponent::ComponentType::YEAR, 2015)
479 .Build()}));
480
481 EXPECT_TRUE(ParsesCorrectly(
482 "{9/28/2011 2:23:15 PM}", 1317212595000, GRANULARITY_SECOND,
483 {DatetimeComponentsBuilder()
484 .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
485 .Add(DatetimeComponent::ComponentType::SECOND, 15)
486 .Add(DatetimeComponent::ComponentType::MINUTE, 23)
487 .Add(DatetimeComponent::ComponentType::HOUR, 2)
488 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 28)
489 .Add(DatetimeComponent::ComponentType::MONTH, 9)
490 .Add(DatetimeComponent::ComponentType::YEAR, 2011)
491 .Build()}));
492 }
493
TEST_F(GrammarDatetimeParserTest,NotEnabledModeHasNoResult)494 TEST_F(GrammarDatetimeParserTest, NotEnabledModeHasNoResult) {
495 ResetParser(ModeFlag_SELECTION);
496 // `DateTimeParserTest` implementation parses the input under the ANNOTATION
497 // mode.
498 EXPECT_TRUE(HasNoResult("{January 1, 1988}"));
499 }
500
TEST_F(GrammarDatetimeParserTest,DateValidation)501 TEST_F(GrammarDatetimeParserTest, DateValidation) {
502 EXPECT_TRUE(ParsesCorrectly(
503 "{01/02/2020}", 1577919600000, GRANULARITY_DAY,
504 {DatetimeComponentsBuilder()
505 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 2)
506 .Add(DatetimeComponent::ComponentType::MONTH, 1)
507 .Add(DatetimeComponent::ComponentType::YEAR, 2020)
508 .Build()}));
509 EXPECT_TRUE(ParsesCorrectly(
510 "{21/02/2020}", 1582239600000, GRANULARITY_DAY,
511 {DatetimeComponentsBuilder()
512 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 21)
513 .Add(DatetimeComponent::ComponentType::MONTH, 2)
514 .Add(DatetimeComponent::ComponentType::YEAR, 2020)
515 .Build()}));
516 }
517
TEST_F(GrammarDatetimeParserTest,OnlyRelativeDatetime)518 TEST_F(GrammarDatetimeParserTest, OnlyRelativeDatetime) {
519 EXPECT_TRUE(
520 ParsesCorrectly("{in 3 hours}", 10800000, GRANULARITY_HOUR,
521 {DatetimeComponentsBuilder()
522 .Add(DatetimeComponent::ComponentType::HOUR, 0,
523 DatetimeComponent::RelativeQualifier::FUTURE, 3)
524 .Build()}));
525 EXPECT_TRUE(ParsesCorrectly(
526 "{wednesday at 4am}", 529200000, GRANULARITY_HOUR,
527 {DatetimeComponentsBuilder()
528 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
529 .Add(DatetimeComponent::ComponentType::HOUR, 4)
530 .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 4,
531 DatetimeComponent::RelativeQualifier::THIS, 0)
532 .Build()}));
533 EXPECT_TRUE(ParsesCorrectly(
534 "set an alarm for {7am tomorrow}", 108000000, GRANULARITY_HOUR,
535 {DatetimeComponentsBuilder()
536 .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
537 .Add(DatetimeComponent::ComponentType::HOUR, 7)
538 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
539 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
540 .Build()}));
541 EXPECT_TRUE(ParsesCorrectly(
542 "called you {last Saturday}",
543 -432000000 /* Fri 1969-12-26 16:00:00 PST */, GRANULARITY_DAY,
544 {DatetimeComponentsBuilder()
545 .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 7,
546 DatetimeComponent::RelativeQualifier::PAST, -1)
547 .Build()},
548 /*anchor_start_end=*/false,
549 /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
550 /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
551 }
552
TEST_F(GrammarDatetimeParserTest,NamedMonthDate)553 TEST_F(GrammarDatetimeParserTest, NamedMonthDate) {
554 EXPECT_TRUE(ParsesCorrectly(
555 "{march 1, 2017}", 1488355200000, GRANULARITY_DAY,
556 {DatetimeComponentsBuilder()
557 .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
558 .Add(DatetimeComponent::ComponentType::MONTH, 3)
559 .Add(DatetimeComponent::ComponentType::YEAR, 2017)
560 .Build()},
561 false, "America/Los_Angeles", "en-US",
562 AnnotationUsecase_ANNOTATION_USECASE_SMART));
563 }
564
565 } // namespace
566 } // namespace libtextclassifier3
567