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