xref: /aosp_15_r20/external/libtextclassifier/native/annotator/datetime/grammar-parser_test.cc (revision 993b0882672172b81d12fad7a7ac0c3e5c824a12)
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