/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "annotator/datetime/grammar-parser.h" #include #include #include "annotator/datetime/datetime-grounder.h" #include "annotator/datetime/testing/base-parser-test.h" #include "annotator/datetime/testing/datetime-component-builder.h" #include "utils/grammar/analyzer.h" #include "utils/jvm-test-utils.h" #include "utils/test-data-test-utils.h" #include "gmock/gmock.h" #include "gtest/gtest.h" using ::libtextclassifier3::grammar::Analyzer; using ::libtextclassifier3::grammar::RulesSet; namespace libtextclassifier3 { namespace { std::string GetModelPath() { return GetTestDataPath("annotator/test_data/"); } std::string ReadFile(const std::string& file_name) { std::ifstream file_stream(file_name); return std::string(std::istreambuf_iterator(file_stream), {}); } class GrammarDatetimeParserTest : public DateTimeParserTest { public: void SetUp() override { grammar_buffer_ = ReadFile(GetModelPath() + "datetime.fb"); unilib_ = CreateUniLibForTesting(); calendarlib_ = CreateCalendarLibForTesting(); analyzer_ = std::make_unique( unilib_.get(), flatbuffers::GetRoot(grammar_buffer_.data())); datetime_grounder_ = std::make_unique(calendarlib_.get()); parser_.reset(new GrammarDatetimeParser(*analyzer_, *datetime_grounder_, /*target_classification_score=*/1.0, /*priority_score=*/1.0)); } // Exposes the date time parser for tests and evaluations. const DatetimeParser* DatetimeParserForTests() const override { return parser_.get(); } private: std::string grammar_buffer_; std::unique_ptr unilib_; std::unique_ptr calendarlib_; std::unique_ptr analyzer_; std::unique_ptr datetime_grounder_; std::unique_ptr parser_; }; TEST_F(GrammarDatetimeParserTest, ParseShort) { EXPECT_TRUE(ParsesCorrectly( "{01/02/2020}", 1580511600000, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1) .Add(DatetimeComponent::ComponentType::MONTH, 2) .Add(DatetimeComponent::ComponentType::YEAR, 2020) .Build()}, /*anchor_start_end=*/false, /*timezone=*/"Europe/Zurich", /*locales=*/"en-GB")); EXPECT_TRUE(ParsesCorrectly( "{01/02/2020}", 1577919600000, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 2) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2020) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{January 1, 1988}", 567990000000, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 1988) .Build()})); } TEST_F(GrammarDatetimeParserTest, Parse) { EXPECT_TRUE(ParsesCorrectly( "{January 1, 1988}", 567990000000, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 1988) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{january 31 2018}", 1517353200000, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 31) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2018) .Build()})); EXPECT_TRUE(ParsesCorrectly( "foo {1 january 2018} bar", 1514761200000, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2018) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{09/Mar/2004 22:02:40}", 1078866160000, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::SECOND, 40) .Add(DatetimeComponent::ComponentType::MINUTE, 02) .Add(DatetimeComponent::ComponentType::HOUR, 22) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 9) .Add(DatetimeComponent::ComponentType::MONTH, 3) .Add(DatetimeComponent::ComponentType::YEAR, 2004) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{Dec 2, 2010 2:39:58 AM}", 1291253998000, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 58) .Add(DatetimeComponent::ComponentType::MINUTE, 39) .Add(DatetimeComponent::ComponentType::HOUR, 2) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 2) .Add(DatetimeComponent::ComponentType::MONTH, 12) .Add(DatetimeComponent::ComponentType::YEAR, 2010) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{Jun 09 2011 15:28:14}", 1307626094000, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::SECOND, 14) .Add(DatetimeComponent::ComponentType::MINUTE, 28) .Add(DatetimeComponent::ComponentType::HOUR, 15) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 9) .Add(DatetimeComponent::ComponentType::MONTH, 6) .Add(DatetimeComponent::ComponentType::YEAR, 2011) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{2010-06-26 02:31:29}", {1277512289000, 1277555489000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 29) .Add(DatetimeComponent::ComponentType::MINUTE, 31) .Add(DatetimeComponent::ComponentType::HOUR, 2) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 26) .Add(DatetimeComponent::ComponentType::MONTH, 6) .Add(DatetimeComponent::ComponentType::YEAR, 2010) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 29) .Add(DatetimeComponent::ComponentType::MINUTE, 31) .Add(DatetimeComponent::ComponentType::HOUR, 2) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 26) .Add(DatetimeComponent::ComponentType::MONTH, 6) .Add(DatetimeComponent::ComponentType::YEAR, 2010) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{2006/01/22 04:11:05}", {1137899465000, 1137942665000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 5) .Add(DatetimeComponent::ComponentType::MINUTE, 11) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 22) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2006) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 5) .Add(DatetimeComponent::ComponentType::MINUTE, 11) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 22) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2006) .Build()})); EXPECT_TRUE( ParsesCorrectly("{11:42:35}", {38555000, 81755000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{23/Apr 11:42:35}", {9715355000, 9758555000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{23/Apr/2015 11:42:35}", {1429782155000, 1429825355000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{23-Apr-2015 11:42:35}", {1429782155000, 1429825355000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{23 Apr 2015 11:42:35}", {1429782155000, 1429825355000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build()})); EXPECT_TRUE(ParsesCorrectly( "Are sentiments apartments decisively the especially alteration. " "Thrown shy denote ten ladies though ask saw. Or by to he going " "think order event music. Incommode so intention defective at " "convinced. Led income months itself and houses you. After nor " "you leave might share court balls. {19/apr/2010 06:36:15} Are " "sentiments apartments decisively the especially alteration. " "Thrown shy denote ten ladies though ask saw. Or by to he going " "think order event music. Incommode so intention defective at " "convinced. Led income months itself and houses you. After nor " "you leave might share court balls. ", {1271651775000, 1271694975000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 15) .Add(DatetimeComponent::ComponentType::MINUTE, 36) .Add(DatetimeComponent::ComponentType::HOUR, 6) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2010) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 15) .Add(DatetimeComponent::ComponentType::MINUTE, 36) .Add(DatetimeComponent::ComponentType::HOUR, 6) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 19) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2010) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{january 1 2018 at 4:30}", {1514777400000, 1514820600000}, GRANULARITY_MINUTE, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::MINUTE, 30) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2018) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::MINUTE, 30) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2018) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{january 1 2018 at 4:30 am}", 1514777400000, GRANULARITY_MINUTE, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::MINUTE, 30) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2018) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{january 1 2018 at 4pm}", 1514818800000, GRANULARITY_HOUR, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2018) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{today at 0:00}", {-3600000, 39600000}, GRANULARITY_MINUTE, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::MINUTE, 0) .Add(DatetimeComponent::ComponentType::HOUR, 0) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0, DatetimeComponent::RelativeQualifier::NOW, 0) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::MINUTE, 0) .Add(DatetimeComponent::ComponentType::HOUR, 0) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0, DatetimeComponent::RelativeQualifier::NOW, 0) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{today at 0:00}", {-57600000, -14400000}, GRANULARITY_MINUTE, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::MINUTE, 0) .Add(DatetimeComponent::ComponentType::HOUR, 0) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0, DatetimeComponent::RelativeQualifier::NOW, 0) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::MINUTE, 0) .Add(DatetimeComponent::ComponentType::HOUR, 0) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0, DatetimeComponent::RelativeQualifier::NOW, 0) .Build()}, /*anchor_start_end=*/false, "America/Los_Angeles")); EXPECT_TRUE(ParsesCorrectly( "{tomorrow at 4:00}", {97200000, 140400000}, GRANULARITY_MINUTE, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::MINUTE, 0) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0, DatetimeComponent::RelativeQualifier::TOMORROW, 1) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::MINUTE, 0) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0, DatetimeComponent::RelativeQualifier::TOMORROW, 1) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{tomorrow at 4am}", 97200000, GRANULARITY_HOUR, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0, DatetimeComponent::RelativeQualifier::TOMORROW, 1) .Build()})); EXPECT_TRUE(ParsesCorrectly( "last seen {today at 9:01 PM}", 72060000, GRANULARITY_MINUTE, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::MINUTE, 1) .Add(DatetimeComponent::ComponentType::HOUR, 9) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0, DatetimeComponent::RelativeQualifier::NOW, 0) .Build()})); EXPECT_TRUE( ParsesCorrectly("set an alarm for {7 a.m}", 21600000, GRANULARITY_HOUR, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::HOUR, 7) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{04/23/15 11:42:35}", {1429782155000, 1429825355000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{04/23/2015 11:42:35}", {1429782155000, 1429825355000}, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build(), DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 35) .Add(DatetimeComponent::ComponentType::MINUTE, 42) .Add(DatetimeComponent::ComponentType::HOUR, 11) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 23) .Add(DatetimeComponent::ComponentType::MONTH, 4) .Add(DatetimeComponent::ComponentType::YEAR, 2015) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{9/28/2011 2:23:15 PM}", 1317212595000, GRANULARITY_SECOND, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 1) .Add(DatetimeComponent::ComponentType::SECOND, 15) .Add(DatetimeComponent::ComponentType::MINUTE, 23) .Add(DatetimeComponent::ComponentType::HOUR, 2) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 28) .Add(DatetimeComponent::ComponentType::MONTH, 9) .Add(DatetimeComponent::ComponentType::YEAR, 2011) .Build()})); } TEST_F(GrammarDatetimeParserTest, DateValidation) { EXPECT_TRUE(ParsesCorrectly( "{01/02/2020}", 1577919600000, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 2) .Add(DatetimeComponent::ComponentType::MONTH, 1) .Add(DatetimeComponent::ComponentType::YEAR, 2020) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{21/02/2020}", 1582239600000, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 21) .Add(DatetimeComponent::ComponentType::MONTH, 2) .Add(DatetimeComponent::ComponentType::YEAR, 2020) .Build()})); } TEST_F(GrammarDatetimeParserTest, OnlyRelativeDatetime) { EXPECT_TRUE( ParsesCorrectly("{in 3 hours}", 10800000, GRANULARITY_HOUR, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::HOUR, 0, DatetimeComponent::RelativeQualifier::FUTURE, 3) .Build()})); EXPECT_TRUE(ParsesCorrectly( "{wednesday at 4am}", 529200000, GRANULARITY_HOUR, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::HOUR, 4) .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 4, DatetimeComponent::RelativeQualifier::THIS, 0) .Build()})); EXPECT_TRUE(ParsesCorrectly( "set an alarm for {7am tomorrow}", 108000000, GRANULARITY_HOUR, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::MERIDIEM, 0) .Add(DatetimeComponent::ComponentType::HOUR, 7) .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 0, DatetimeComponent::RelativeQualifier::TOMORROW, 1) .Build()})); EXPECT_TRUE(ParsesCorrectly( "called you {last Saturday}", -432000000 /* Fri 1969-12-26 16:00:00 PST */, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_WEEK, 7, DatetimeComponent::RelativeQualifier::PAST, -1) .Build()}, /*anchor_start_end=*/false, /*timezone=*/"Europe/Zurich", /*locales=*/"en-US", /*annotation_usecase=*/AnnotationUsecase_ANNOTATION_USECASE_RAW)); } TEST_F(GrammarDatetimeParserTest, NamedMonthDate) { EXPECT_TRUE(ParsesCorrectly( "{march 1, 2017}", 1488355200000, GRANULARITY_DAY, {DatetimeComponentsBuilder() .Add(DatetimeComponent::ComponentType::DAY_OF_MONTH, 1) .Add(DatetimeComponent::ComponentType::MONTH, 3) .Add(DatetimeComponent::ComponentType::YEAR, 2017) .Build()}, false, "America/Los_Angeles", "en-US", AnnotationUsecase_ANNOTATION_USECASE_SMART)); } } // namespace } // namespace libtextclassifier3