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/regex-parser.h"
18 
19 #include <time.h>
20 
21 #include <fstream>
22 #include <iostream>
23 #include <memory>
24 #include <string>
25 
26 #include "annotator/annotator.h"
27 #include "annotator/datetime/testing/base-parser-test.h"
28 #include "annotator/datetime/testing/datetime-component-builder.h"
29 #include "annotator/model_generated.h"
30 #include "annotator/types-test-util.h"
31 #include "utils/i18n/locale-list.h"
32 #include "utils/jvm-test-utils.h"
33 #include "utils/test-data-test-utils.h"
34 #include "utils/testing/annotator.h"
35 #include "gmock/gmock.h"
36 #include "gtest/gtest.h"
37 
38 using std::vector;
39 
40 namespace libtextclassifier3 {
41 namespace {
GetModelPath()42 std::string GetModelPath() { return GetTestDataPath("annotator/test_data/"); }
43 
ReadFile(const std::string & file_name)44 std::string ReadFile(const std::string& file_name) {
45   std::ifstream file_stream(file_name);
46   return std::string(std::istreambuf_iterator<char>(file_stream), {});
47 }
48 
49 class RegexDatetimeParserTest : public DateTimeParserTest {
50  public:
SetUp()51   void SetUp() override {
52     // Loads default unmodified model. Individual tests can call LoadModel to
53     // make changes.
54     LoadModel(
55         [](ModelT* model) { model->datetime_grammar_model.reset(nullptr); });
56   }
57 
58   template <typename Fn>
LoadModel(Fn model_visitor_fn)59   void LoadModel(Fn model_visitor_fn) {
60     std::string model_buffer = ReadFile(GetModelPath() + "test_model.fb");
61     model_buffer_ = ModifyAnnotatorModel(model_buffer, model_visitor_fn);
62     unilib_ = CreateUniLibForTesting();
63     calendarlib_ = CreateCalendarLibForTesting();
64     classifier_ =
65         Annotator::FromUnownedBuffer(model_buffer_.data(), model_buffer_.size(),
66                                      unilib_.get(), calendarlib_.get());
67     TC3_CHECK(classifier_);
68     parser_ = classifier_->DatetimeParserForTests();
69     TC3_CHECK(parser_);
70   }
71 
72   // Exposes the date time parser for tests and evaluations.
DatetimeParserForTests() const73   const DatetimeParser* DatetimeParserForTests() const override {
74     return classifier_->DatetimeParserForTests();
75   }
76 
77  private:
78   std::string model_buffer_;
79   std::unique_ptr<Annotator> classifier_;
80   const DatetimeParser* parser_;
81   std::unique_ptr<UniLib> unilib_;
82   std::unique_ptr<CalendarLib> calendarlib_;
83 };
84 
85 // Test with just a few cases to make debugging of general failures easier.
TEST_F(RegexDatetimeParserTest,ParseShort)86 TEST_F(RegexDatetimeParserTest, ParseShort) {
87   EXPECT_TRUE(ParsesCorrectly(
88       "{January 1, 1988}", 567990000000, GRANULARITY_DAY,
89       {DatetimeComponentsBuilder()
90            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
91            .Add(DatetimeComponent::ComponentType::MONTH, 1)
92            .Add(DatetimeComponent::ComponentType::YEAR, 1988)
93            .Build()}));
94 }
95 
TEST_F(RegexDatetimeParserTest,Parse)96 TEST_F(RegexDatetimeParserTest, Parse) {
97   EXPECT_TRUE(ParsesCorrectly(
98       "{January 1, 1988}", 567990000000, GRANULARITY_DAY,
99       {DatetimeComponentsBuilder()
100            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
101            .Add(DatetimeComponent::ComponentType::MONTH, 1)
102            .Add(DatetimeComponent::ComponentType::YEAR, 1988)
103            .Build()}));
104   EXPECT_TRUE(ParsesCorrectly(
105       "{january 31 2018}", 1517353200000, GRANULARITY_DAY,
106       {DatetimeComponentsBuilder()
107            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 31)
108            .Add(DatetimeComponent::ComponentType::MONTH, 1)
109            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
110            .Build()}));
111   EXPECT_TRUE(ParsesCorrectly(
112       "lorem {1 january 2018} ipsum", 1514761200000, GRANULARITY_DAY,
113       {DatetimeComponentsBuilder()
114            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
115            .Add(DatetimeComponent::ComponentType::MONTH, 1)
116            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
117            .Build()}));
118   EXPECT_TRUE(ParsesCorrectly(
119       "{09/Mar/2004 22:02:40}", 1078866160000, GRANULARITY_SECOND,
120       {DatetimeComponentsBuilder()
121            .Add(DatetimeComponent::ComponentType::SECOND, 40)
122            .Add(DatetimeComponent::ComponentType::MINUTE, 02)
123            .Add(DatetimeComponent::ComponentType::HOUR, 22)
124            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 9)
125            .Add(DatetimeComponent::ComponentType::MONTH, 3)
126            .Add(DatetimeComponent::ComponentType::YEAR, 2004)
127            .Build()}));
128   EXPECT_TRUE(ParsesCorrectly(
129       "{Dec 2, 2010 2:39:58 AM}", 1291253998000, GRANULARITY_SECOND,
130       {DatetimeComponentsBuilder()
131            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
132            .Add(DatetimeComponent::ComponentType::SECOND, 58)
133            .Add(DatetimeComponent::ComponentType::MINUTE, 39)
134            .Add(DatetimeComponent::ComponentType::HOUR, 2)
135            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 2)
136            .Add(DatetimeComponent::ComponentType::MONTH, 12)
137            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
138            .Build()}));
139   EXPECT_TRUE(ParsesCorrectly(
140       "{Jun 09 2011 15:28:14}", 1307626094000, GRANULARITY_SECOND,
141       {DatetimeComponentsBuilder()
142            .Add(DatetimeComponent::ComponentType::SECOND, 14)
143            .Add(DatetimeComponent::ComponentType::MINUTE, 28)
144            .Add(DatetimeComponent::ComponentType::HOUR, 15)
145            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 9)
146            .Add(DatetimeComponent::ComponentType::MONTH, 6)
147            .Add(DatetimeComponent::ComponentType::YEAR, 2011)
148            .Build()}));
149   EXPECT_TRUE(ParsesCorrectly(
150       "{Mar 16 08:12:04}", {6419524000, 6462724000}, GRANULARITY_SECOND,
151       {DatetimeComponentsBuilder()
152            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
153            .Add(DatetimeComponent::ComponentType::SECOND, 4)
154            .Add(DatetimeComponent::ComponentType::MINUTE, 12)
155            .Add(DatetimeComponent::ComponentType::HOUR, 8)
156            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 16)
157            .Add(DatetimeComponent::ComponentType::MONTH, 3)
158            .Build(),
159        DatetimeComponentsBuilder()
160            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
161            .Add(DatetimeComponent::ComponentType::SECOND, 4)
162            .Add(DatetimeComponent::ComponentType::MINUTE, 12)
163            .Add(DatetimeComponent::ComponentType::HOUR, 8)
164            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 16)
165            .Add(DatetimeComponent::ComponentType::MONTH, 3)
166            .Build()}));
167   EXPECT_TRUE(ParsesCorrectly(
168       "{2010-06-26 02:31:29}", {1277512289000, 1277555489000},
169       GRANULARITY_SECOND,
170       {DatetimeComponentsBuilder()
171            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
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        DatetimeComponentsBuilder()
180            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
181            .Add(DatetimeComponent::ComponentType::SECOND, 29)
182            .Add(DatetimeComponent::ComponentType::MINUTE, 31)
183            .Add(DatetimeComponent::ComponentType::HOUR, 2)
184            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 26)
185            .Add(DatetimeComponent::ComponentType::MONTH, 6)
186            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
187            .Build()}));
188   EXPECT_TRUE(ParsesCorrectly(
189       "{2006/01/22 04:11:05}", {1137899465000, 1137942665000},
190       GRANULARITY_SECOND,
191       {DatetimeComponentsBuilder()
192            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
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        DatetimeComponentsBuilder()
201            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
202            .Add(DatetimeComponent::ComponentType::SECOND, 5)
203            .Add(DatetimeComponent::ComponentType::MINUTE, 11)
204            .Add(DatetimeComponent::ComponentType::HOUR, 4)
205            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 22)
206            .Add(DatetimeComponent::ComponentType::MONTH, 1)
207            .Add(DatetimeComponent::ComponentType::YEAR, 2006)
208            .Build()}));
209   EXPECT_TRUE(
210       ParsesCorrectly("{11:42:35}", {38555000, 81755000}, 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                            .Build(),
217                        DatetimeComponentsBuilder()
218                            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
219                            .Add(DatetimeComponent::ComponentType::SECOND, 35)
220                            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
221                            .Add(DatetimeComponent::ComponentType::HOUR, 11)
222                            .Build()}));
223   EXPECT_TRUE(ParsesCorrectly(
224       "{23/Apr 11:42:35}", {9715355000, 9758555000}, GRANULARITY_SECOND,
225       {DatetimeComponentsBuilder()
226            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
227            .Add(DatetimeComponent::ComponentType::SECOND, 35)
228            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
229            .Add(DatetimeComponent::ComponentType::HOUR, 11)
230            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
231            .Add(DatetimeComponent::ComponentType::MONTH, 4)
232            .Build(),
233        DatetimeComponentsBuilder()
234            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
235            .Add(DatetimeComponent::ComponentType::SECOND, 35)
236            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
237            .Add(DatetimeComponent::ComponentType::HOUR, 11)
238            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
239            .Add(DatetimeComponent::ComponentType::MONTH, 4)
240            .Build()}));
241   EXPECT_TRUE(ParsesCorrectly(
242       "{23/Apr/2015 11:42:35}", {1429782155000, 1429825355000},
243       GRANULARITY_SECOND,
244       {DatetimeComponentsBuilder()
245            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
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        DatetimeComponentsBuilder()
254            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
255            .Add(DatetimeComponent::ComponentType::SECOND, 35)
256            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
257            .Add(DatetimeComponent::ComponentType::HOUR, 11)
258            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
259            .Add(DatetimeComponent::ComponentType::MONTH, 4)
260            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
261            .Build()}));
262   EXPECT_TRUE(ParsesCorrectly(
263       "{23-Apr-2015 11:42:35}", {1429782155000, 1429825355000},
264       GRANULARITY_SECOND,
265       {DatetimeComponentsBuilder()
266            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
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        DatetimeComponentsBuilder()
275            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
276            .Add(DatetimeComponent::ComponentType::SECOND, 35)
277            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
278            .Add(DatetimeComponent::ComponentType::HOUR, 11)
279            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
280            .Add(DatetimeComponent::ComponentType::MONTH, 4)
281            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
282            .Build()}));
283   EXPECT_TRUE(ParsesCorrectly(
284       "{23 Apr 2015 11:42:35}", {1429782155000, 1429825355000},
285       GRANULARITY_SECOND,
286       {DatetimeComponentsBuilder()
287            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
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        DatetimeComponentsBuilder()
296            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
297            .Add(DatetimeComponent::ComponentType::SECOND, 35)
298            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
299            .Add(DatetimeComponent::ComponentType::HOUR, 11)
300            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
301            .Add(DatetimeComponent::ComponentType::MONTH, 4)
302            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
303            .Build()}));
304   EXPECT_TRUE(ParsesCorrectly(
305       "{04/23/15 11:42:35}", {1429782155000, 1429825355000}, GRANULARITY_SECOND,
306       {DatetimeComponentsBuilder()
307            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
308            .Add(DatetimeComponent::ComponentType::SECOND, 35)
309            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
310            .Add(DatetimeComponent::ComponentType::HOUR, 11)
311            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
312            .Add(DatetimeComponent::ComponentType::MONTH, 4)
313            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
314            .Build(),
315        DatetimeComponentsBuilder()
316            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
317            .Add(DatetimeComponent::ComponentType::SECOND, 35)
318            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
319            .Add(DatetimeComponent::ComponentType::HOUR, 11)
320            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
321            .Add(DatetimeComponent::ComponentType::MONTH, 4)
322            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
323            .Build()}));
324   EXPECT_TRUE(ParsesCorrectly(
325       "{04/23/2015 11:42:35}", {1429782155000, 1429825355000},
326       GRANULARITY_SECOND,
327       {DatetimeComponentsBuilder()
328            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
329            .Add(DatetimeComponent::ComponentType::SECOND, 35)
330            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
331            .Add(DatetimeComponent::ComponentType::HOUR, 11)
332            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
333            .Add(DatetimeComponent::ComponentType::MONTH, 4)
334            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
335            .Build(),
336        DatetimeComponentsBuilder()
337            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
338            .Add(DatetimeComponent::ComponentType::SECOND, 35)
339            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
340            .Add(DatetimeComponent::ComponentType::HOUR, 11)
341            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
342            .Add(DatetimeComponent::ComponentType::MONTH, 4)
343            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
344            .Build()}));
345   EXPECT_TRUE(ParsesCorrectly(
346       "{9/28/2011 2:23:15 PM}", 1317212595000, GRANULARITY_SECOND,
347       {DatetimeComponentsBuilder()
348            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
349            .Add(DatetimeComponent::ComponentType::SECOND, 15)
350            .Add(DatetimeComponent::ComponentType::MINUTE, 23)
351            .Add(DatetimeComponent::ComponentType::HOUR, 2)
352            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 28)
353            .Add(DatetimeComponent::ComponentType::MONTH, 9)
354            .Add(DatetimeComponent::ComponentType::YEAR, 2011)
355            .Build()}));
356   EXPECT_TRUE(ParsesCorrectly(
357       "Are sentiments apartments decisively the especially alteration. "
358       "Thrown shy denote ten ladies though ask saw. Or by to he going "
359       "think order event music. Incommode so intention defective at "
360       "convinced. Led income months itself and houses you. After nor "
361       "you leave might share court balls. {19/apr/2010 06:36:15} Are "
362       "sentiments apartments decisively the especially alteration. "
363       "Thrown shy denote ten ladies though ask saw. Or by to he going "
364       "think order event music. Incommode so intention defective at "
365       "convinced. Led income months itself and houses you. After nor "
366       "you leave might share court balls. ",
367       {1271651775000, 1271694975000}, GRANULARITY_SECOND,
368       {DatetimeComponentsBuilder()
369            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
370            .Add(DatetimeComponent::ComponentType::SECOND, 15)
371            .Add(DatetimeComponent::ComponentType::MINUTE, 36)
372            .Add(DatetimeComponent::ComponentType::HOUR, 6)
373            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19)
374            .Add(DatetimeComponent::ComponentType::MONTH, 4)
375            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
376            .Build(),
377        DatetimeComponentsBuilder()
378            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
379            .Add(DatetimeComponent::ComponentType::SECOND, 15)
380            .Add(DatetimeComponent::ComponentType::MINUTE, 36)
381            .Add(DatetimeComponent::ComponentType::HOUR, 6)
382            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19)
383            .Add(DatetimeComponent::ComponentType::MONTH, 4)
384            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
385            .Build()}));
386   EXPECT_TRUE(ParsesCorrectly(
387       "{january 1 2018 at 4:30}", {1514777400000, 1514820600000},
388       GRANULARITY_MINUTE,
389       {DatetimeComponentsBuilder()
390            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
391            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
392            .Add(DatetimeComponent::ComponentType::HOUR, 4)
393            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
394            .Add(DatetimeComponent::ComponentType::MONTH, 1)
395            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
396            .Build(),
397        DatetimeComponentsBuilder()
398            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
399            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
400            .Add(DatetimeComponent::ComponentType::HOUR, 4)
401            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
402            .Add(DatetimeComponent::ComponentType::MONTH, 1)
403            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
404            .Build()}));
405   EXPECT_TRUE(ParsesCorrectly(
406       "{january 1 2018 at 4:30 am}", 1514777400000, GRANULARITY_MINUTE,
407       {DatetimeComponentsBuilder()
408            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
409            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
410            .Add(DatetimeComponent::ComponentType::HOUR, 4)
411            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
412            .Add(DatetimeComponent::ComponentType::MONTH, 1)
413            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
414            .Build()}));
415   EXPECT_TRUE(ParsesCorrectly(
416       "{january 1 2018 at 4pm}", 1514818800000, GRANULARITY_HOUR,
417       {DatetimeComponentsBuilder()
418            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
419            .Add(DatetimeComponent::ComponentType::HOUR, 4)
420            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
421            .Add(DatetimeComponent::ComponentType::MONTH, 1)
422            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
423            .Build()}));
424 
425   EXPECT_TRUE(ParsesCorrectly(
426       "{today at 0:00}", {-3600000, 39600000}, GRANULARITY_MINUTE,
427       {DatetimeComponentsBuilder()
428            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
429            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
430            .Add(DatetimeComponent::ComponentType::HOUR, 0)
431            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
432                 DatetimeComponent::RelativeQualifier::NOW, 0)
433            .Build(),
434        DatetimeComponentsBuilder()
435            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
436            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
437            .Add(DatetimeComponent::ComponentType::HOUR, 0)
438            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
439                 DatetimeComponent::RelativeQualifier::NOW, 0)
440            .Build()}));
441   EXPECT_TRUE(ParsesCorrectly(
442       "{today at 0:00}", {-57600000, -14400000}, GRANULARITY_MINUTE,
443       {DatetimeComponentsBuilder()
444            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
445            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
446            .Add(DatetimeComponent::ComponentType::HOUR, 0)
447            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
448                 DatetimeComponent::RelativeQualifier::NOW, 0)
449            .Build(),
450        DatetimeComponentsBuilder()
451            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
452            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
453            .Add(DatetimeComponent::ComponentType::HOUR, 0)
454            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
455                 DatetimeComponent::RelativeQualifier::NOW, 0)
456            .Build()},
457       /*anchor_start_end=*/false, "America/Los_Angeles"));
458   EXPECT_TRUE(ParsesCorrectly(
459       "{tomorrow at 4:00}", {97200000, 140400000}, GRANULARITY_MINUTE,
460       {DatetimeComponentsBuilder()
461            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
462            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
463            .Add(DatetimeComponent::ComponentType::HOUR, 4)
464            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
465                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
466            .Build(),
467        DatetimeComponentsBuilder()
468            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
469            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
470            .Add(DatetimeComponent::ComponentType::HOUR, 4)
471            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
472                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
473            .Build()}));
474   EXPECT_TRUE(ParsesCorrectly(
475       "{tomorrow at 4am}", 97200000, GRANULARITY_HOUR,
476       {DatetimeComponentsBuilder()
477            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
478            .Add(DatetimeComponent::ComponentType::HOUR, 4)
479            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
480                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
481            .Build()}));
482   EXPECT_TRUE(ParsesCorrectly(
483       "{wednesday at 4am}", 529200000, GRANULARITY_HOUR,
484       {DatetimeComponentsBuilder()
485            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
486            .Add(DatetimeComponent::ComponentType::HOUR, 4)
487            .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 4,
488                 DatetimeComponent::RelativeQualifier::THIS, 0)
489            .Build()}));
490   EXPECT_TRUE(ParsesCorrectly(
491       "last seen {today at 9:01 PM}", 72060000, GRANULARITY_MINUTE,
492       {DatetimeComponentsBuilder()
493            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
494            .Add(DatetimeComponent::ComponentType::MINUTE, 1)
495            .Add(DatetimeComponent::ComponentType::HOUR, 9)
496            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
497                 DatetimeComponent::RelativeQualifier::NOW, 0)
498            .Build()}));
499   EXPECT_TRUE(ParsesCorrectly(
500       "set an alarm for {7am tomorrow}", 108000000, GRANULARITY_HOUR,
501       {DatetimeComponentsBuilder()
502            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
503            .Add(DatetimeComponent::ComponentType::HOUR, 7)
504            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
505                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
506            .Build()}));
507   EXPECT_TRUE(
508       ParsesCorrectly("set an alarm for {7 a.m}", 21600000, GRANULARITY_HOUR,
509                       {DatetimeComponentsBuilder()
510                            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
511                            .Add(DatetimeComponent::ComponentType::HOUR, 7)
512                            .Build()}));
513 
514   EXPECT_TRUE(ParsesCorrectly(
515       "lets meet by {noon}", 39600000, GRANULARITY_MINUTE,
516       {DatetimeComponentsBuilder()
517            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
518            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
519            .Add(DatetimeComponent::ComponentType::HOUR, 12)
520            .Build()},
521       /*anchor_start_end=*/false,
522       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
523       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
524 
525   EXPECT_TRUE(ParsesCorrectly(
526       "at {midnight}", 82800000, GRANULARITY_MINUTE,
527       {DatetimeComponentsBuilder()
528            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
529            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
530            .Add(DatetimeComponent::ComponentType::HOUR, 0)
531            .Build()},
532       /*anchor_start_end=*/false,
533       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
534       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
535 }
536 
TEST_F(RegexDatetimeParserTest,ParseWithAnchor)537 TEST_F(RegexDatetimeParserTest, ParseWithAnchor) {
538   EXPECT_TRUE(ParsesCorrectly(
539       "{January 1, 1988}", 567990000000, GRANULARITY_DAY,
540       {DatetimeComponentsBuilder()
541            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
542            .Add(DatetimeComponent::ComponentType::MONTH, 1)
543            .Add(DatetimeComponent::ComponentType::YEAR, 1988)
544            .Build()},
545       /*anchor_start_end=*/false));
546   EXPECT_TRUE(ParsesCorrectly(
547       "{January 1, 1988}", 567990000000, GRANULARITY_DAY,
548       {DatetimeComponentsBuilder()
549            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
550            .Add(DatetimeComponent::ComponentType::MONTH, 1)
551            .Add(DatetimeComponent::ComponentType::YEAR, 1988)
552            .Build()},
553       /*anchor_start_end=*/true));
554   EXPECT_TRUE(ParsesCorrectly(
555       "lorem {1 january 2018} ipsum", 1514761200000, GRANULARITY_DAY,
556       {DatetimeComponentsBuilder()
557            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
558            .Add(DatetimeComponent::ComponentType::MONTH, 1)
559            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
560            .Build()},
561       /*anchor_start_end=*/false));
562   EXPECT_TRUE(HasNoResult("lorem 1 january 2018 ipsum",
563                           /*anchor_start_end=*/true));
564 }
565 
TEST_F(RegexDatetimeParserTest,ParseWithRawUsecase)566 TEST_F(RegexDatetimeParserTest, ParseWithRawUsecase) {
567   // Annotated for RAW usecase.
568   EXPECT_TRUE(ParsesCorrectly(
569       "{tomorrow}", 82800000, GRANULARITY_DAY,
570       {DatetimeComponentsBuilder()
571            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
572                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
573            .Build()},
574       /*anchor_start_end=*/false,
575       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
576       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
577 
578   EXPECT_TRUE(ParsesCorrectly(
579       "call me {in two hours}", 7200000, GRANULARITY_HOUR,
580       {DatetimeComponentsBuilder()
581            .Add(DatetimeComponent::ComponentType::HOUR, 0,
582                 DatetimeComponent::RelativeQualifier::FUTURE, 2)
583            .Build()},
584       /*anchor_start_end=*/false,
585       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
586       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
587 
588   EXPECT_TRUE(ParsesCorrectly(
589       "call me {next month}", 2674800000, GRANULARITY_MONTH,
590       {DatetimeComponentsBuilder()
591            .Add(DatetimeComponent::ComponentType::MONTH, 0,
592                 DatetimeComponent::RelativeQualifier::NEXT, 1)
593            .Build()},
594       /*anchor_start_end=*/false,
595       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
596       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
597   EXPECT_TRUE(ParsesCorrectly(
598       "what's the time {now}", -3600000, GRANULARITY_DAY,
599       {DatetimeComponentsBuilder()
600            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
601                 DatetimeComponent::RelativeQualifier::NOW, 0)
602            .Build()},
603       /*anchor_start_end=*/false,
604       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
605       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
606 
607   EXPECT_TRUE(ParsesCorrectly(
608       "call me on {Saturday}", 169200000, GRANULARITY_DAY,
609       {DatetimeComponentsBuilder()
610            .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 7,
611                 DatetimeComponent::RelativeQualifier::THIS, 0)
612            .Build()},
613       /*anchor_start_end=*/false,
614       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
615       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
616 
617   // Not annotated for Smart usecase.
618   EXPECT_TRUE(HasNoResult(
619       "{tomorrow}", /*anchor_start_end=*/false,
620       /*timezone=*/"Europe/Zurich",
621       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_SMART));
622 }
623 
624 // For details please see b/155437137
TEST_F(RegexDatetimeParserTest,PastRelativeDatetime)625 TEST_F(RegexDatetimeParserTest, PastRelativeDatetime) {
626   EXPECT_TRUE(ParsesCorrectly(
627       "called you {last Saturday}",
628       -432000000 /* Fri 1969-12-26 16:00:00 PST */, GRANULARITY_DAY,
629       {DatetimeComponentsBuilder()
630            .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 7,
631                 DatetimeComponent::RelativeQualifier::PAST, -1)
632            .Build()},
633       /*anchor_start_end=*/false,
634       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
635       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
636 
637   EXPECT_TRUE(ParsesCorrectly(
638       "called you {last year}", -31536000000 /* Tue 1968-12-31 16:00:00 PST */,
639       GRANULARITY_YEAR,
640       {DatetimeComponentsBuilder()
641            .Add(DatetimeComponent::ComponentType::YEAR, 0,
642                 DatetimeComponent::RelativeQualifier::PAST, -1)
643            .Build()},
644       /*anchor_start_end=*/false,
645       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
646       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
647 
648   EXPECT_TRUE(ParsesCorrectly(
649       "called you {last month}", -2678400000 /* Sun 1969-11-30 16:00:00 PST */,
650       GRANULARITY_MONTH,
651       {DatetimeComponentsBuilder()
652            .Add(DatetimeComponent::ComponentType::MONTH, 0,
653                 DatetimeComponent::RelativeQualifier::PAST, -1)
654            .Build()},
655       /*anchor_start_end=*/false,
656       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
657       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
658 
659   EXPECT_TRUE(ParsesCorrectly(
660       "called you {yesterday}", -90000000, /* Tue 1969-12-30 15:00:00 PST */
661       GRANULARITY_DAY,
662       {DatetimeComponentsBuilder()
663            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
664                 DatetimeComponent::RelativeQualifier::YESTERDAY, -1)
665            .Build()},
666       /*anchor_start_end=*/false,
667       /*timezone=*/"Europe/Zurich", /*locales=*/"en-US",
668       /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW));
669 }
670 
TEST_F(RegexDatetimeParserTest,AddsADayWhenTimeInThePastAndDayNotSpecified)671 TEST_F(RegexDatetimeParserTest, AddsADayWhenTimeInThePastAndDayNotSpecified) {
672   // ParsesCorrectly uses 0 as the reference time, which corresponds to:
673   // "Thu Jan 01 1970 01:00:00" Zurich time. So if we pass "0:30" here, it means
674   // it is in the past, and so the parser should move this to the next day ->
675   // "Fri Jan 02 1970 00:30:00" Zurich time (b/139112907).
676   EXPECT_TRUE(ParsesCorrectly(
677       "{0:30am}", 84600000L /* 23.5 hours from reference time */,
678       GRANULARITY_MINUTE,
679       {DatetimeComponentsBuilder()
680            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
681            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
682            .Add(DatetimeComponent::ComponentType::HOUR, 0)
683            .Build()}));
684 }
685 
TEST_F(RegexDatetimeParserTest,DoesNotAddADayWhenTimeInThePastAndDayNotSpecifiedDisabled)686 TEST_F(RegexDatetimeParserTest,
687        DoesNotAddADayWhenTimeInThePastAndDayNotSpecifiedDisabled) {
688   // ParsesCorrectly uses 0 as the reference time, which corresponds to:
689   // "Thu Jan 01 1970 01:00:00" Zurich time. So if we pass "0:30" here, it means
690   // it is in the past. The parameter prefer_future_when_unspecified_day is
691   // disabled, so the parser should annotate this to the same day: "Thu Jan 01
692   // 1970 00:30:00" Zurich time.
693   LoadModel([](ModelT* model) {
694     // In the test model, the prefer_future_for_unspecified_date is true; make
695     // it false only for this test.
696     model->datetime_model->prefer_future_for_unspecified_date = false;
697     model->datetime_grammar_model.reset(nullptr);
698   });
699 
700   EXPECT_TRUE(ParsesCorrectly(
701       "{0:30am}", -1800000L /* -30 minutes from reference time */,
702       GRANULARITY_MINUTE,
703       {DatetimeComponentsBuilder()
704            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
705            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
706            .Add(DatetimeComponent::ComponentType::HOUR, 0)
707            .Build()}));
708 }
709 
TEST_F(RegexDatetimeParserTest,ParsesNoonAndMidnightCorrectly)710 TEST_F(RegexDatetimeParserTest, ParsesNoonAndMidnightCorrectly) {
711   EXPECT_TRUE(ParsesCorrectly(
712       "{January 1, 1988 12:30am}", 567991800000, GRANULARITY_MINUTE,
713       {DatetimeComponentsBuilder()
714            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
715            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
716            .Add(DatetimeComponent::ComponentType::HOUR, 12)
717            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
718            .Add(DatetimeComponent::ComponentType::MONTH, 1)
719            .Add(DatetimeComponent::ComponentType::YEAR, 1988)
720            .Build()}));
721   EXPECT_TRUE(ParsesCorrectly(
722       "{January 1, 1988 12:30pm}", 568035000000, GRANULARITY_MINUTE,
723       {DatetimeComponentsBuilder()
724            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
725            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
726            .Add(DatetimeComponent::ComponentType::HOUR, 12)
727            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
728            .Add(DatetimeComponent::ComponentType::MONTH, 1)
729            .Add(DatetimeComponent::ComponentType::YEAR, 1988)
730            .Build()}));
731   EXPECT_TRUE(ParsesCorrectly(
732       "{tomorrow at 12:00 am}", 82800000, GRANULARITY_MINUTE,
733       {DatetimeComponentsBuilder()
734            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
735            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
736            .Add(DatetimeComponent::ComponentType::HOUR, 12)
737            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
738                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
739            .Build()}));
740 }
741 
TEST_F(RegexDatetimeParserTest,ParseGerman)742 TEST_F(RegexDatetimeParserTest, ParseGerman) {
743   EXPECT_TRUE(ParsesCorrectlyGerman(
744       "{Januar 1 2018}", 1514761200000, GRANULARITY_DAY,
745       {DatetimeComponentsBuilder()
746            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
747            .Add(DatetimeComponent::ComponentType::MONTH, 1)
748            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
749            .Build()}));
750   EXPECT_TRUE(ParsesCorrectlyGerman(
751       "{1/2/2018}", 1517439600000, GRANULARITY_DAY,
752       {DatetimeComponentsBuilder()
753            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
754            .Add(DatetimeComponent::ComponentType::MONTH, 2)
755            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
756            .Build()}));
757   EXPECT_TRUE(ParsesCorrectlyGerman(
758       "lorem {1 Januar 2018} ipsum", 1514761200000, GRANULARITY_DAY,
759       {DatetimeComponentsBuilder()
760            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
761            .Add(DatetimeComponent::ComponentType::MONTH, 1)
762            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
763            .Build()}));
764   EXPECT_TRUE(ParsesCorrectlyGerman(
765       "{19/Apr/2010:06:36:15}", {1271651775000, 1271694975000},
766       GRANULARITY_SECOND,
767       {DatetimeComponentsBuilder()
768            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
769            .Add(DatetimeComponent::ComponentType::SECOND, 15)
770            .Add(DatetimeComponent::ComponentType::MINUTE, 36)
771            .Add(DatetimeComponent::ComponentType::HOUR, 6)
772            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19)
773            .Add(DatetimeComponent::ComponentType::MONTH, 4)
774            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
775            .Build(),
776        DatetimeComponentsBuilder()
777            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
778            .Add(DatetimeComponent::ComponentType::SECOND, 15)
779            .Add(DatetimeComponent::ComponentType::MINUTE, 36)
780            .Add(DatetimeComponent::ComponentType::HOUR, 6)
781            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19)
782            .Add(DatetimeComponent::ComponentType::MONTH, 4)
783            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
784            .Build()}));
785   EXPECT_TRUE(ParsesCorrectlyGerman(
786       "{09/März/2004 22:02:40}", 1078866160000, GRANULARITY_SECOND,
787       {DatetimeComponentsBuilder()
788            .Add(DatetimeComponent::ComponentType::SECOND, 40)
789            .Add(DatetimeComponent::ComponentType::MINUTE, 02)
790            .Add(DatetimeComponent::ComponentType::HOUR, 22)
791            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 9)
792            .Add(DatetimeComponent::ComponentType::MONTH, 3)
793            .Add(DatetimeComponent::ComponentType::YEAR, 2004)
794            .Build()}));
795   EXPECT_TRUE(ParsesCorrectlyGerman(
796       "{Dez 2, 2010 2:39:58}", {1291253998000, 1291297198000},
797       GRANULARITY_SECOND,
798       {DatetimeComponentsBuilder()
799            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
800            .Add(DatetimeComponent::ComponentType::SECOND, 58)
801            .Add(DatetimeComponent::ComponentType::MINUTE, 39)
802            .Add(DatetimeComponent::ComponentType::HOUR, 2)
803            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 2)
804            .Add(DatetimeComponent::ComponentType::MONTH, 12)
805            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
806            .Build(),
807        DatetimeComponentsBuilder()
808            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
809            .Add(DatetimeComponent::ComponentType::SECOND, 58)
810            .Add(DatetimeComponent::ComponentType::MINUTE, 39)
811            .Add(DatetimeComponent::ComponentType::HOUR, 2)
812            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 2)
813            .Add(DatetimeComponent::ComponentType::MONTH, 12)
814            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
815            .Build()}));
816   EXPECT_TRUE(ParsesCorrectlyGerman(
817       "{Juni 09 2011 15:28:14}", 1307626094000, GRANULARITY_SECOND,
818       {DatetimeComponentsBuilder()
819            .Add(DatetimeComponent::ComponentType::SECOND, 14)
820            .Add(DatetimeComponent::ComponentType::MINUTE, 28)
821            .Add(DatetimeComponent::ComponentType::HOUR, 15)
822            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 9)
823            .Add(DatetimeComponent::ComponentType::MONTH, 6)
824            .Add(DatetimeComponent::ComponentType::YEAR, 2011)
825            .Build()}));
826   EXPECT_TRUE(ParsesCorrectlyGerman(
827       "{März 16 08:12:04}", {6419524000, 6462724000}, GRANULARITY_SECOND,
828       {DatetimeComponentsBuilder()
829            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
830            .Add(DatetimeComponent::ComponentType::SECOND, 4)
831            .Add(DatetimeComponent::ComponentType::MINUTE, 12)
832            .Add(DatetimeComponent::ComponentType::HOUR, 8)
833            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 16)
834            .Add(DatetimeComponent::ComponentType::MONTH, 3)
835            .Build(),
836        DatetimeComponentsBuilder()
837            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
838            .Add(DatetimeComponent::ComponentType::SECOND, 4)
839            .Add(DatetimeComponent::ComponentType::MINUTE, 12)
840            .Add(DatetimeComponent::ComponentType::HOUR, 8)
841            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 16)
842            .Add(DatetimeComponent::ComponentType::MONTH, 3)
843            .Build()}));
844   EXPECT_TRUE(ParsesCorrectlyGerman(
845       "{2010-06-26 02:31:29}", {1277512289000, 1277555489000},
846       GRANULARITY_SECOND,
847       {DatetimeComponentsBuilder()
848            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
849            .Add(DatetimeComponent::ComponentType::SECOND, 29)
850            .Add(DatetimeComponent::ComponentType::MINUTE, 31)
851            .Add(DatetimeComponent::ComponentType::HOUR, 2)
852            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 26)
853            .Add(DatetimeComponent::ComponentType::MONTH, 6)
854            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
855            .Build(),
856        DatetimeComponentsBuilder()
857            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
858            .Add(DatetimeComponent::ComponentType::SECOND, 29)
859            .Add(DatetimeComponent::ComponentType::MINUTE, 31)
860            .Add(DatetimeComponent::ComponentType::HOUR, 2)
861            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 26)
862            .Add(DatetimeComponent::ComponentType::MONTH, 6)
863            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
864            .Build()}));
865   EXPECT_TRUE(ParsesCorrectlyGerman(
866       "{2006/01/22 04:11:05}", {1137899465000, 1137942665000},
867       GRANULARITY_SECOND,
868       {DatetimeComponentsBuilder()
869            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
870            .Add(DatetimeComponent::ComponentType::SECOND, 5)
871            .Add(DatetimeComponent::ComponentType::MINUTE, 11)
872            .Add(DatetimeComponent::ComponentType::HOUR, 4)
873            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 22)
874            .Add(DatetimeComponent::ComponentType::MONTH, 1)
875            .Add(DatetimeComponent::ComponentType::YEAR, 2006)
876            .Build(),
877        DatetimeComponentsBuilder()
878            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
879            .Add(DatetimeComponent::ComponentType::SECOND, 5)
880            .Add(DatetimeComponent::ComponentType::MINUTE, 11)
881            .Add(DatetimeComponent::ComponentType::HOUR, 4)
882            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 22)
883            .Add(DatetimeComponent::ComponentType::MONTH, 1)
884            .Add(DatetimeComponent::ComponentType::YEAR, 2006)
885            .Build()}));
886   EXPECT_TRUE(ParsesCorrectlyGerman(
887       "{11:42:35}", {38555000, 81755000}, GRANULARITY_SECOND,
888       {DatetimeComponentsBuilder()
889            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
890            .Add(DatetimeComponent::ComponentType::SECOND, 35)
891            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
892            .Add(DatetimeComponent::ComponentType::HOUR, 11)
893            .Build(),
894        DatetimeComponentsBuilder()
895            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
896            .Add(DatetimeComponent::ComponentType::SECOND, 35)
897            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
898            .Add(DatetimeComponent::ComponentType::HOUR, 11)
899            .Build()}));
900   EXPECT_TRUE(ParsesCorrectlyGerman(
901       "{23/Apr 11:42:35}", {9715355000, 9758555000}, GRANULARITY_SECOND,
902       {DatetimeComponentsBuilder()
903            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
904            .Add(DatetimeComponent::ComponentType::SECOND, 35)
905            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
906            .Add(DatetimeComponent::ComponentType::HOUR, 11)
907            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
908            .Add(DatetimeComponent::ComponentType::MONTH, 4)
909            .Build(),
910        DatetimeComponentsBuilder()
911            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
912            .Add(DatetimeComponent::ComponentType::SECOND, 35)
913            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
914            .Add(DatetimeComponent::ComponentType::HOUR, 11)
915            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
916            .Add(DatetimeComponent::ComponentType::MONTH, 4)
917            .Build()}));
918   EXPECT_TRUE(ParsesCorrectlyGerman(
919       "{23/Apr/2015:11:42:35}", {1429782155000, 1429825355000},
920       GRANULARITY_SECOND,
921       {DatetimeComponentsBuilder()
922            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
923            .Add(DatetimeComponent::ComponentType::SECOND, 35)
924            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
925            .Add(DatetimeComponent::ComponentType::HOUR, 11)
926            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
927            .Add(DatetimeComponent::ComponentType::MONTH, 4)
928            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
929            .Build(),
930        DatetimeComponentsBuilder()
931            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
932            .Add(DatetimeComponent::ComponentType::SECOND, 35)
933            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
934            .Add(DatetimeComponent::ComponentType::HOUR, 11)
935            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
936            .Add(DatetimeComponent::ComponentType::MONTH, 4)
937            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
938            .Build()}));
939   EXPECT_TRUE(ParsesCorrectlyGerman(
940       "{23/Apr/2015 11:42:35}", {1429782155000, 1429825355000},
941       GRANULARITY_SECOND,
942       {DatetimeComponentsBuilder()
943            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
944            .Add(DatetimeComponent::ComponentType::SECOND, 35)
945            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
946            .Add(DatetimeComponent::ComponentType::HOUR, 11)
947            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
948            .Add(DatetimeComponent::ComponentType::MONTH, 4)
949            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
950            .Build(),
951        DatetimeComponentsBuilder()
952            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
953            .Add(DatetimeComponent::ComponentType::SECOND, 35)
954            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
955            .Add(DatetimeComponent::ComponentType::HOUR, 11)
956            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
957            .Add(DatetimeComponent::ComponentType::MONTH, 4)
958            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
959            .Build()}));
960   EXPECT_TRUE(ParsesCorrectlyGerman(
961       "{23-Apr-2015 11:42:35}", {1429782155000, 1429825355000},
962       GRANULARITY_SECOND,
963       {DatetimeComponentsBuilder()
964            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
965            .Add(DatetimeComponent::ComponentType::SECOND, 35)
966            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
967            .Add(DatetimeComponent::ComponentType::HOUR, 11)
968            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
969            .Add(DatetimeComponent::ComponentType::MONTH, 4)
970            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
971            .Build(),
972        DatetimeComponentsBuilder()
973            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
974            .Add(DatetimeComponent::ComponentType::SECOND, 35)
975            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
976            .Add(DatetimeComponent::ComponentType::HOUR, 11)
977            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
978            .Add(DatetimeComponent::ComponentType::MONTH, 4)
979            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
980            .Build()}));
981   EXPECT_TRUE(ParsesCorrectlyGerman(
982       "{23 Apr 2015 11:42:35}", {1429782155000, 1429825355000},
983       GRANULARITY_SECOND,
984       {DatetimeComponentsBuilder()
985            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
986            .Add(DatetimeComponent::ComponentType::SECOND, 35)
987            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
988            .Add(DatetimeComponent::ComponentType::HOUR, 11)
989            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
990            .Add(DatetimeComponent::ComponentType::MONTH, 4)
991            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
992            .Build(),
993        DatetimeComponentsBuilder()
994            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
995            .Add(DatetimeComponent::ComponentType::SECOND, 35)
996            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
997            .Add(DatetimeComponent::ComponentType::HOUR, 11)
998            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
999            .Add(DatetimeComponent::ComponentType::MONTH, 4)
1000            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
1001            .Build()}));
1002   EXPECT_TRUE(ParsesCorrectlyGerman(
1003       "{04/23/15 11:42:35}", {1429782155000, 1429825355000}, GRANULARITY_SECOND,
1004       {DatetimeComponentsBuilder()
1005            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1006            .Add(DatetimeComponent::ComponentType::SECOND, 35)
1007            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
1008            .Add(DatetimeComponent::ComponentType::HOUR, 11)
1009            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
1010            .Add(DatetimeComponent::ComponentType::MONTH, 4)
1011            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
1012            .Build(),
1013        DatetimeComponentsBuilder()
1014            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1015            .Add(DatetimeComponent::ComponentType::SECOND, 35)
1016            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
1017            .Add(DatetimeComponent::ComponentType::HOUR, 11)
1018            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
1019            .Add(DatetimeComponent::ComponentType::MONTH, 4)
1020            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
1021            .Build()}));
1022   EXPECT_TRUE(ParsesCorrectlyGerman(
1023       "{04/23/2015 11:42:35}", {1429782155000, 1429825355000},
1024       GRANULARITY_SECOND,
1025       {DatetimeComponentsBuilder()
1026            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1027            .Add(DatetimeComponent::ComponentType::SECOND, 35)
1028            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
1029            .Add(DatetimeComponent::ComponentType::HOUR, 11)
1030            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
1031            .Add(DatetimeComponent::ComponentType::MONTH, 4)
1032            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
1033            .Build(),
1034        DatetimeComponentsBuilder()
1035            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1036            .Add(DatetimeComponent::ComponentType::SECOND, 35)
1037            .Add(DatetimeComponent::ComponentType::MINUTE, 42)
1038            .Add(DatetimeComponent::ComponentType::HOUR, 11)
1039            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23)
1040            .Add(DatetimeComponent::ComponentType::MONTH, 4)
1041            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
1042            .Build()}));
1043   EXPECT_TRUE(ParsesCorrectlyGerman(
1044       "{19/apr/2010:06:36:15}", {1271651775000, 1271694975000},
1045       GRANULARITY_SECOND,
1046       {DatetimeComponentsBuilder()
1047            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1048            .Add(DatetimeComponent::ComponentType::SECOND, 15)
1049            .Add(DatetimeComponent::ComponentType::MINUTE, 36)
1050            .Add(DatetimeComponent::ComponentType::HOUR, 6)
1051            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19)
1052            .Add(DatetimeComponent::ComponentType::MONTH, 4)
1053            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
1054            .Build(),
1055        DatetimeComponentsBuilder()
1056            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1057            .Add(DatetimeComponent::ComponentType::SECOND, 15)
1058            .Add(DatetimeComponent::ComponentType::MINUTE, 36)
1059            .Add(DatetimeComponent::ComponentType::HOUR, 6)
1060            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19)
1061            .Add(DatetimeComponent::ComponentType::MONTH, 4)
1062            .Add(DatetimeComponent::ComponentType::YEAR, 2010)
1063            .Build()}));
1064   EXPECT_TRUE(ParsesCorrectlyGerman(
1065       "{januar 1 2018 um 4:30}", {1514777400000, 1514820600000},
1066       GRANULARITY_MINUTE,
1067       {DatetimeComponentsBuilder()
1068            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1069            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
1070            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1071            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
1072            .Add(DatetimeComponent::ComponentType::MONTH, 1)
1073            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
1074            .Build(),
1075        DatetimeComponentsBuilder()
1076            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1077            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
1078            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1079            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
1080            .Add(DatetimeComponent::ComponentType::MONTH, 1)
1081            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
1082            .Build()}));
1083   EXPECT_TRUE(ParsesCorrectlyGerman(
1084       "{januar 1 2018 um 4:30 nachm}", 1514820600000, GRANULARITY_MINUTE,
1085       {DatetimeComponentsBuilder()
1086            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1087            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
1088            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1089            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
1090            .Add(DatetimeComponent::ComponentType::MONTH, 1)
1091            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
1092            .Build()}));
1093   EXPECT_TRUE(ParsesCorrectlyGerman(
1094       "{januar 1 2018 um 4 nachm}", 1514818800000, GRANULARITY_HOUR,
1095       {DatetimeComponentsBuilder()
1096            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1097            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1098            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
1099            .Add(DatetimeComponent::ComponentType::MONTH, 1)
1100            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
1101            .Build()}));
1102   EXPECT_TRUE(ParsesCorrectlyGerman(
1103       "{14.03.2017}", 1489446000000, GRANULARITY_DAY,
1104       {DatetimeComponentsBuilder()
1105            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 14)
1106            .Add(DatetimeComponent::ComponentType::MONTH, 3)
1107            .Add(DatetimeComponent::ComponentType::YEAR, 2017)
1108            .Build()}));
1109 
1110   EXPECT_TRUE(ParsesCorrectlyGerman(
1111       "{morgen 0:00}", {82800000, 126000000}, GRANULARITY_MINUTE,
1112       {DatetimeComponentsBuilder()
1113            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1114            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
1115            .Add(DatetimeComponent::ComponentType::HOUR, 0)
1116            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
1117                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
1118            .Build(),
1119        DatetimeComponentsBuilder()
1120            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1121            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
1122            .Add(DatetimeComponent::ComponentType::HOUR, 0)
1123            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
1124                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
1125            .Build()}));
1126   EXPECT_TRUE(ParsesCorrectlyGerman(
1127       "{morgen um 4:00}", {97200000, 140400000}, GRANULARITY_MINUTE,
1128       {DatetimeComponentsBuilder()
1129            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1130            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
1131            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1132            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
1133                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
1134            .Build(),
1135        DatetimeComponentsBuilder()
1136            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1137            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
1138            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1139            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
1140                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
1141            .Build()}));
1142   EXPECT_TRUE(ParsesCorrectlyGerman(
1143       "{morgen um 4 vorm}", 97200000, GRANULARITY_HOUR,
1144       {DatetimeComponentsBuilder()
1145            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1146            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1147            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
1148                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
1149            .Build()}));
1150 }
1151 
TEST_F(RegexDatetimeParserTest,ParseChinese)1152 TEST_F(RegexDatetimeParserTest, ParseChinese) {
1153   EXPECT_TRUE(ParsesCorrectlyChinese(
1154       "{明天 7 上午}", 108000000, GRANULARITY_HOUR,
1155       {DatetimeComponentsBuilder()
1156            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1157            .Add(DatetimeComponent::ComponentType::HOUR, 7)
1158            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0,
1159                 DatetimeComponent::RelativeQualifier::TOMORROW, 1)
1160            .Build()}));
1161 }
1162 
TEST_F(RegexDatetimeParserTest,ParseNonUs)1163 TEST_F(RegexDatetimeParserTest, ParseNonUs) {
1164   auto first_may_2015 =
1165       DatetimeComponentsBuilder()
1166           .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
1167           .Add(DatetimeComponent::ComponentType::MONTH, 5)
1168           .Add(DatetimeComponent::ComponentType::YEAR, 2015)
1169           .Build();
1170 
1171   EXPECT_TRUE(ParsesCorrectly("{1/5/2015}", 1430431200000, GRANULARITY_DAY,
1172                               {first_may_2015},
1173                               /*anchor_start_end=*/false,
1174                               /*timezone=*/"Europe/Zurich",
1175                               /*locales=*/"en-GB"));
1176   EXPECT_TRUE(ParsesCorrectly("{1/5/2015}", 1430431200000, GRANULARITY_DAY,
1177                               {first_may_2015},
1178                               /*anchor_start_end=*/false,
1179                               /*timezone=*/"Europe/Zurich", /*locales=*/"en"));
1180 }
1181 
TEST_F(RegexDatetimeParserTest,ParseUs)1182 TEST_F(RegexDatetimeParserTest, ParseUs) {
1183   auto five_january_2015 =
1184       DatetimeComponentsBuilder()
1185           .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 5)
1186           .Add(DatetimeComponent::ComponentType::MONTH, 1)
1187           .Add(DatetimeComponent::ComponentType::YEAR, 2015)
1188           .Build();
1189 
1190   EXPECT_TRUE(ParsesCorrectly("{1/5/2015}", 1420412400000, GRANULARITY_DAY,
1191                               {five_january_2015},
1192                               /*anchor_start_end=*/false,
1193                               /*timezone=*/"Europe/Zurich",
1194                               /*locales=*/"en-US"));
1195   EXPECT_TRUE(ParsesCorrectly("{1/5/2015}", 1420412400000, GRANULARITY_DAY,
1196                               {five_january_2015},
1197                               /*anchor_start_end=*/false,
1198                               /*timezone=*/"Europe/Zurich",
1199                               /*locales=*/"es-US"));
1200 }
1201 
TEST_F(RegexDatetimeParserTest,ParseUnknownLanguage)1202 TEST_F(RegexDatetimeParserTest, ParseUnknownLanguage) {
1203   EXPECT_TRUE(ParsesCorrectly(
1204       "bylo to {31. 12. 2015} v 6 hodin", 1451516400000, GRANULARITY_DAY,
1205       {DatetimeComponentsBuilder()
1206            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 31)
1207            .Add(DatetimeComponent::ComponentType::MONTH, 12)
1208            .Add(DatetimeComponent::ComponentType::YEAR, 2015)
1209            .Build()},
1210       /*anchor_start_end=*/false,
1211       /*timezone=*/"Europe/Zurich", /*locales=*/"xx"));
1212 }
1213 
TEST_F(RegexDatetimeParserTest,WhenAlternativesEnabledGeneratesAlternatives)1214 TEST_F(RegexDatetimeParserTest, WhenAlternativesEnabledGeneratesAlternatives) {
1215   LoadModel([](ModelT* model) {
1216     model->datetime_model->generate_alternative_interpretations_when_ambiguous =
1217         true;
1218   });
1219 
1220   EXPECT_TRUE(ParsesCorrectly(
1221       "{january 1 2018 at 4:30}", {1514777400000, 1514820600000},
1222       GRANULARITY_MINUTE,
1223       {DatetimeComponentsBuilder()
1224            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1225            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
1226            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1227            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
1228            .Add(DatetimeComponent::ComponentType::MONTH, 1)
1229            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
1230            .Build(),
1231        DatetimeComponentsBuilder()
1232            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1233            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
1234            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1235            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
1236            .Add(DatetimeComponent::ComponentType::MONTH, 1)
1237            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
1238            .Build()}));
1239   EXPECT_TRUE(ParsesCorrectly(
1240       "{monday 3pm}", 396000000, GRANULARITY_HOUR,
1241       {DatetimeComponentsBuilder()
1242            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1243            .Add(DatetimeComponent::ComponentType::HOUR, 3)
1244            .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 2,
1245                 DatetimeComponent::RelativeQualifier::THIS, 0)
1246            .Build()}));
1247   EXPECT_TRUE(ParsesCorrectly(
1248       "{monday 3:00}", {352800000, 396000000}, GRANULARITY_MINUTE,
1249       {DatetimeComponentsBuilder()
1250            .Add(DatetimeComponent::ComponentType::MERIDIEM, 0)
1251            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
1252            .Add(DatetimeComponent::ComponentType::HOUR, 3)
1253            .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 2,
1254                 DatetimeComponent::RelativeQualifier::THIS, 0)
1255            .Build(),
1256        DatetimeComponentsBuilder()
1257            .Add(DatetimeComponent::ComponentType::MERIDIEM, 1)
1258            .Add(DatetimeComponent::ComponentType::MINUTE, 0)
1259            .Add(DatetimeComponent::ComponentType::HOUR, 3)
1260            .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 2,
1261                 DatetimeComponent::RelativeQualifier::THIS, 0)
1262            .Build()}));
1263 }
1264 
TEST_F(RegexDatetimeParserTest,WhenAlternativesDisabledDoesNotGenerateAlternatives)1265 TEST_F(RegexDatetimeParserTest,
1266        WhenAlternativesDisabledDoesNotGenerateAlternatives) {
1267   LoadModel([](ModelT* model) {
1268     model->datetime_model->generate_alternative_interpretations_when_ambiguous =
1269         false;
1270     model->datetime_grammar_model.reset(nullptr);
1271   });
1272 
1273   EXPECT_TRUE(ParsesCorrectly(
1274       "{january 1 2018 at 4:30}", 1514777400000, GRANULARITY_MINUTE,
1275       {DatetimeComponentsBuilder()
1276            .Add(DatetimeComponent::ComponentType::MINUTE, 30)
1277            .Add(DatetimeComponent::ComponentType::HOUR, 4)
1278            .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1)
1279            .Add(DatetimeComponent::ComponentType::MONTH, 1)
1280            .Add(DatetimeComponent::ComponentType::YEAR, 2018)
1281            .Build()}));
1282 }
1283 
1284 class ParserLocaleTest : public testing::Test {
1285  public:
1286   void SetUp() override;
1287   bool HasResult(const std::string& input, const std::string& locales);
1288 
1289  protected:
1290   std::unique_ptr<UniLib> unilib_;
1291   std::unique_ptr<CalendarLib> calendarlib_;
1292   flatbuffers::FlatBufferBuilder builder_;
1293   std::unique_ptr<DatetimeParser> parser_;
1294 };
1295 
AddPattern(const std::string & regex,int locale,std::vector<std::unique_ptr<DatetimeModelPatternT>> * patterns)1296 void AddPattern(const std::string& regex, int locale,
1297                 std::vector<std::unique_ptr<DatetimeModelPatternT>>* patterns) {
1298   patterns->emplace_back(new DatetimeModelPatternT);
1299   patterns->back()->regexes.emplace_back(new DatetimeModelPattern_::RegexT);
1300   patterns->back()->regexes.back()->pattern = regex;
1301   patterns->back()->regexes.back()->groups.push_back(
1302       DatetimeGroupType_GROUP_UNUSED);
1303   patterns->back()->locales.push_back(locale);
1304 }
1305 
SetUp()1306 void ParserLocaleTest::SetUp() {
1307   DatetimeModelT model;
1308   model.use_extractors_for_locating = false;
1309   model.locales.clear();
1310   model.locales.push_back("en-US");
1311   model.locales.push_back("en-CH");
1312   model.locales.push_back("zh-Hant");
1313   model.locales.push_back("en-*");
1314   model.locales.push_back("zh-Hant-*");
1315   model.locales.push_back("*-CH");
1316   model.locales.push_back("default");
1317   model.default_locales.push_back(6);
1318 
1319   AddPattern(/*regex=*/"en-US", /*locale=*/0, &model.patterns);
1320   AddPattern(/*regex=*/"en-CH", /*locale=*/1, &model.patterns);
1321   AddPattern(/*regex=*/"zh-Hant", /*locale=*/2, &model.patterns);
1322   AddPattern(/*regex=*/"en-all", /*locale=*/3, &model.patterns);
1323   AddPattern(/*regex=*/"zh-Hant-all", /*locale=*/4, &model.patterns);
1324   AddPattern(/*regex=*/"all-CH", /*locale=*/5, &model.patterns);
1325   AddPattern(/*regex=*/"default", /*locale=*/6, &model.patterns);
1326 
1327   builder_.Finish(DatetimeModel::Pack(builder_, &model));
1328   const DatetimeModel* model_fb =
1329       flatbuffers::GetRoot<DatetimeModel>(builder_.GetBufferPointer());
1330   ASSERT_TRUE(model_fb);
1331 
1332   unilib_ = CreateUniLibForTesting();
1333   calendarlib_ = CreateCalendarLibForTesting();
1334   parser_ =
1335       RegexDatetimeParser::Instance(model_fb, unilib_.get(), calendarlib_.get(),
1336                                     /*decompressor=*/nullptr);
1337   ASSERT_TRUE(parser_);
1338 }
1339 
HasResult(const std::string & input,const std::string & locales)1340 bool ParserLocaleTest::HasResult(const std::string& input,
1341                                  const std::string& locales) {
1342   StatusOr<std::vector<DatetimeParseResultSpan>> results = parser_->Parse(
1343       input, /*reference_time_ms_utc=*/0,
1344       /*reference_timezone=*/"", LocaleList::ParseFrom(locales),
1345       ModeFlag_ANNOTATION, AnnotationUsecase_ANNOTATION_USECASE_SMART, false);
1346   EXPECT_TRUE(results.ok());
1347   return results.ValueOrDie().size() == 1;
1348 }
1349 
TEST_F(ParserLocaleTest,English)1350 TEST_F(ParserLocaleTest, English) {
1351   EXPECT_TRUE(HasResult("en-US", /*locales=*/"en-US"));
1352   EXPECT_FALSE(HasResult("en-CH", /*locales=*/"en-US"));
1353   EXPECT_FALSE(HasResult("en-US", /*locales=*/"en-CH"));
1354   EXPECT_TRUE(HasResult("en-CH", /*locales=*/"en-CH"));
1355   EXPECT_TRUE(HasResult("default", /*locales=*/"en-CH"));
1356 }
1357 
TEST_F(ParserLocaleTest,TraditionalChinese)1358 TEST_F(ParserLocaleTest, TraditionalChinese) {
1359   EXPECT_TRUE(HasResult("zh-Hant-all", /*locales=*/"zh-Hant"));
1360   EXPECT_TRUE(HasResult("zh-Hant-all", /*locales=*/"zh-Hant-TW"));
1361   EXPECT_TRUE(HasResult("zh-Hant-all", /*locales=*/"zh-Hant-SG"));
1362   EXPECT_FALSE(HasResult("zh-Hant-all", /*locales=*/"zh-SG"));
1363   EXPECT_FALSE(HasResult("zh-Hant-all", /*locales=*/"zh"));
1364   EXPECT_TRUE(HasResult("default", /*locales=*/"zh"));
1365   EXPECT_TRUE(HasResult("default", /*locales=*/"zh-Hant-SG"));
1366 }
1367 
TEST_F(ParserLocaleTest,SwissEnglish)1368 TEST_F(ParserLocaleTest, SwissEnglish) {
1369   EXPECT_TRUE(HasResult("all-CH", /*locales=*/"de-CH"));
1370   EXPECT_TRUE(HasResult("all-CH", /*locales=*/"en-CH"));
1371   EXPECT_TRUE(HasResult("en-all", /*locales=*/"en-CH"));
1372   EXPECT_FALSE(HasResult("all-CH", /*locales=*/"de-DE"));
1373   EXPECT_TRUE(HasResult("default", /*locales=*/"de-CH"));
1374   EXPECT_TRUE(HasResult("default", /*locales=*/"en-CH"));
1375 }
1376 
1377 }  // namespace
1378 }  // namespace libtextclassifier3
1379