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