1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker *
4*993b0882SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker *
8*993b0882SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker *
10*993b0882SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker */
16*993b0882SAndroid Build Coastguard Worker
17*993b0882SAndroid Build Coastguard Worker #include "annotator/datetime/datetime-grounder.h"
18*993b0882SAndroid Build Coastguard Worker
19*993b0882SAndroid Build Coastguard Worker #include <algorithm>
20*993b0882SAndroid Build Coastguard Worker #include <limits>
21*993b0882SAndroid Build Coastguard Worker #include <unordered_map>
22*993b0882SAndroid Build Coastguard Worker #include <vector>
23*993b0882SAndroid Build Coastguard Worker
24*993b0882SAndroid Build Coastguard Worker #include "annotator/datetime/datetime_generated.h"
25*993b0882SAndroid Build Coastguard Worker #include "annotator/datetime/utils.h"
26*993b0882SAndroid Build Coastguard Worker #include "annotator/types.h"
27*993b0882SAndroid Build Coastguard Worker #include "utils/base/integral_types.h"
28*993b0882SAndroid Build Coastguard Worker #include "utils/base/status.h"
29*993b0882SAndroid Build Coastguard Worker #include "utils/base/status_macros.h"
30*993b0882SAndroid Build Coastguard Worker
31*993b0882SAndroid Build Coastguard Worker using ::libtextclassifier3::grammar::datetime::AbsoluteDateTime;
32*993b0882SAndroid Build Coastguard Worker using ::libtextclassifier3::grammar::datetime::ComponentType;
33*993b0882SAndroid Build Coastguard Worker using ::libtextclassifier3::grammar::datetime::Meridiem;
34*993b0882SAndroid Build Coastguard Worker using ::libtextclassifier3::grammar::datetime::RelativeDateTime;
35*993b0882SAndroid Build Coastguard Worker using ::libtextclassifier3::grammar::datetime::RelativeDatetimeComponent;
36*993b0882SAndroid Build Coastguard Worker using ::libtextclassifier3::grammar::datetime::UngroundedDatetime;
37*993b0882SAndroid Build Coastguard Worker using ::libtextclassifier3::grammar::datetime::RelativeDatetimeComponent_::
38*993b0882SAndroid Build Coastguard Worker Modifier;
39*993b0882SAndroid Build Coastguard Worker
40*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
41*993b0882SAndroid Build Coastguard Worker
42*993b0882SAndroid Build Coastguard Worker namespace {
43*993b0882SAndroid Build Coastguard Worker
44*993b0882SAndroid Build Coastguard Worker const std::unordered_map<int, int> kMonthDefaultLastDayMap(
45*993b0882SAndroid Build Coastguard Worker {{/*no_month*/ 0, 31},
46*993b0882SAndroid Build Coastguard Worker {/*January*/ 1, 31},
47*993b0882SAndroid Build Coastguard Worker {/*Febuary*/ 2, 29},
48*993b0882SAndroid Build Coastguard Worker {/*March*/ 3, 31},
49*993b0882SAndroid Build Coastguard Worker {/*April*/ 4, 30},
50*993b0882SAndroid Build Coastguard Worker {/*May*/ 5, 31},
51*993b0882SAndroid Build Coastguard Worker {/*June*/ 6, 30},
52*993b0882SAndroid Build Coastguard Worker {/*July*/ 7, 31},
53*993b0882SAndroid Build Coastguard Worker {/*August*/ 8, 31},
54*993b0882SAndroid Build Coastguard Worker {/*September*/ 9, 30},
55*993b0882SAndroid Build Coastguard Worker {/*October*/ 10, 31},
56*993b0882SAndroid Build Coastguard Worker {/*November*/ 11, 30},
57*993b0882SAndroid Build Coastguard Worker {/*December*/ 12, 31}});
58*993b0882SAndroid Build Coastguard Worker
IsValidDatetime(const AbsoluteDateTime * absolute_datetime)59*993b0882SAndroid Build Coastguard Worker bool IsValidDatetime(const AbsoluteDateTime* absolute_datetime) {
60*993b0882SAndroid Build Coastguard Worker // Sanity Checks.
61*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->minute() > 59 || absolute_datetime->second() > 59 ||
62*993b0882SAndroid Build Coastguard Worker absolute_datetime->hour() > 23 || absolute_datetime->month() > 12 ||
63*993b0882SAndroid Build Coastguard Worker absolute_datetime->month() == 0) {
64*993b0882SAndroid Build Coastguard Worker return false;
65*993b0882SAndroid Build Coastguard Worker }
66*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->day() >= 0) {
67*993b0882SAndroid Build Coastguard Worker int min_day_value = 1;
68*993b0882SAndroid Build Coastguard Worker int max_day_value = 31;
69*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->month() >= 0 && absolute_datetime->month() <= 12) {
70*993b0882SAndroid Build Coastguard Worker max_day_value = kMonthDefaultLastDayMap.at(absolute_datetime->month());
71*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->day() < min_day_value ||
72*993b0882SAndroid Build Coastguard Worker absolute_datetime->day() > max_day_value) {
73*993b0882SAndroid Build Coastguard Worker return false;
74*993b0882SAndroid Build Coastguard Worker }
75*993b0882SAndroid Build Coastguard Worker }
76*993b0882SAndroid Build Coastguard Worker }
77*993b0882SAndroid Build Coastguard Worker return true;
78*993b0882SAndroid Build Coastguard Worker }
79*993b0882SAndroid Build Coastguard Worker
IsValidDatetime(const RelativeDateTime * relative_datetime)80*993b0882SAndroid Build Coastguard Worker bool IsValidDatetime(const RelativeDateTime* relative_datetime) {
81*993b0882SAndroid Build Coastguard Worker if (relative_datetime->base()) {
82*993b0882SAndroid Build Coastguard Worker return IsValidDatetime(relative_datetime->base());
83*993b0882SAndroid Build Coastguard Worker }
84*993b0882SAndroid Build Coastguard Worker return true;
85*993b0882SAndroid Build Coastguard Worker }
86*993b0882SAndroid Build Coastguard Worker
ToRelativeQualifier(const Modifier & modifier)87*993b0882SAndroid Build Coastguard Worker StatusOr<DatetimeComponent::RelativeQualifier> ToRelativeQualifier(
88*993b0882SAndroid Build Coastguard Worker const Modifier& modifier) {
89*993b0882SAndroid Build Coastguard Worker switch (modifier) {
90*993b0882SAndroid Build Coastguard Worker case Modifier::Modifier_THIS:
91*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::RelativeQualifier::THIS;
92*993b0882SAndroid Build Coastguard Worker case Modifier::Modifier_LAST:
93*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::RelativeQualifier::LAST;
94*993b0882SAndroid Build Coastguard Worker case Modifier::Modifier_NEXT:
95*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::RelativeQualifier::NEXT;
96*993b0882SAndroid Build Coastguard Worker case Modifier::Modifier_NOW:
97*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::RelativeQualifier::NOW;
98*993b0882SAndroid Build Coastguard Worker case Modifier::Modifier_TOMORROW:
99*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::RelativeQualifier::TOMORROW;
100*993b0882SAndroid Build Coastguard Worker case Modifier::Modifier_YESTERDAY:
101*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::RelativeQualifier::YESTERDAY;
102*993b0882SAndroid Build Coastguard Worker case Modifier::Modifier_PAST:
103*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::RelativeQualifier::PAST;
104*993b0882SAndroid Build Coastguard Worker case Modifier::Modifier_FUTURE:
105*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::RelativeQualifier::FUTURE;
106*993b0882SAndroid Build Coastguard Worker case Modifier::Modifier_UNSPECIFIED:
107*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::RelativeQualifier::UNSPECIFIED;
108*993b0882SAndroid Build Coastguard Worker default:
109*993b0882SAndroid Build Coastguard Worker return Status(StatusCode::INTERNAL,
110*993b0882SAndroid Build Coastguard Worker "Couldn't parse the Modifier to RelativeQualifier.");
111*993b0882SAndroid Build Coastguard Worker }
112*993b0882SAndroid Build Coastguard Worker }
113*993b0882SAndroid Build Coastguard Worker
ToComponentType(const grammar::datetime::ComponentType component_type)114*993b0882SAndroid Build Coastguard Worker StatusOr<DatetimeComponent::ComponentType> ToComponentType(
115*993b0882SAndroid Build Coastguard Worker const grammar::datetime::ComponentType component_type) {
116*993b0882SAndroid Build Coastguard Worker switch (component_type) {
117*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_YEAR:
118*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::YEAR;
119*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_MONTH:
120*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::MONTH;
121*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_WEEK:
122*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::WEEK;
123*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_DAY_OF_WEEK:
124*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::DAY_OF_WEEK;
125*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_DAY_OF_MONTH:
126*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::DAY_OF_MONTH;
127*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_HOUR:
128*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::HOUR;
129*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_MINUTE:
130*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::MINUTE;
131*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_SECOND:
132*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::SECOND;
133*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_MERIDIEM:
134*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::MERIDIEM;
135*993b0882SAndroid Build Coastguard Worker case grammar::datetime::ComponentType_UNSPECIFIED:
136*993b0882SAndroid Build Coastguard Worker return DatetimeComponent::ComponentType::UNSPECIFIED;
137*993b0882SAndroid Build Coastguard Worker default:
138*993b0882SAndroid Build Coastguard Worker return Status(StatusCode::INTERNAL,
139*993b0882SAndroid Build Coastguard Worker "Couldn't parse the DatetimeComponent's ComponentType from "
140*993b0882SAndroid Build Coastguard Worker "grammar's datetime ComponentType.");
141*993b0882SAndroid Build Coastguard Worker }
142*993b0882SAndroid Build Coastguard Worker }
143*993b0882SAndroid Build Coastguard Worker
FillAbsoluteDateTimeComponents(const grammar::datetime::AbsoluteDateTime * absolute_datetime,DatetimeParsedData * datetime_parsed_data)144*993b0882SAndroid Build Coastguard Worker void FillAbsoluteDateTimeComponents(
145*993b0882SAndroid Build Coastguard Worker const grammar::datetime::AbsoluteDateTime* absolute_datetime,
146*993b0882SAndroid Build Coastguard Worker DatetimeParsedData* datetime_parsed_data) {
147*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->year() >= 0) {
148*993b0882SAndroid Build Coastguard Worker datetime_parsed_data->SetAbsoluteValue(
149*993b0882SAndroid Build Coastguard Worker DatetimeComponent::ComponentType::YEAR,
150*993b0882SAndroid Build Coastguard Worker GetAdjustedYear(absolute_datetime->year()));
151*993b0882SAndroid Build Coastguard Worker }
152*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->month() >= 0) {
153*993b0882SAndroid Build Coastguard Worker datetime_parsed_data->SetAbsoluteValue(
154*993b0882SAndroid Build Coastguard Worker DatetimeComponent::ComponentType::MONTH, absolute_datetime->month());
155*993b0882SAndroid Build Coastguard Worker }
156*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->day() >= 0) {
157*993b0882SAndroid Build Coastguard Worker datetime_parsed_data->SetAbsoluteValue(
158*993b0882SAndroid Build Coastguard Worker DatetimeComponent::ComponentType::DAY_OF_MONTH,
159*993b0882SAndroid Build Coastguard Worker absolute_datetime->day());
160*993b0882SAndroid Build Coastguard Worker }
161*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->week_day() >= 0) {
162*993b0882SAndroid Build Coastguard Worker datetime_parsed_data->SetAbsoluteValue(
163*993b0882SAndroid Build Coastguard Worker DatetimeComponent::ComponentType::DAY_OF_WEEK,
164*993b0882SAndroid Build Coastguard Worker absolute_datetime->week_day());
165*993b0882SAndroid Build Coastguard Worker }
166*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->hour() >= 0) {
167*993b0882SAndroid Build Coastguard Worker datetime_parsed_data->SetAbsoluteValue(
168*993b0882SAndroid Build Coastguard Worker DatetimeComponent::ComponentType::HOUR, absolute_datetime->hour());
169*993b0882SAndroid Build Coastguard Worker }
170*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->minute() >= 0) {
171*993b0882SAndroid Build Coastguard Worker datetime_parsed_data->SetAbsoluteValue(
172*993b0882SAndroid Build Coastguard Worker DatetimeComponent::ComponentType::MINUTE, absolute_datetime->minute());
173*993b0882SAndroid Build Coastguard Worker }
174*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->second() >= 0) {
175*993b0882SAndroid Build Coastguard Worker datetime_parsed_data->SetAbsoluteValue(
176*993b0882SAndroid Build Coastguard Worker DatetimeComponent::ComponentType::SECOND, absolute_datetime->second());
177*993b0882SAndroid Build Coastguard Worker }
178*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->meridiem() != grammar::datetime::Meridiem_UNKNOWN) {
179*993b0882SAndroid Build Coastguard Worker datetime_parsed_data->SetAbsoluteValue(
180*993b0882SAndroid Build Coastguard Worker DatetimeComponent::ComponentType::MERIDIEM,
181*993b0882SAndroid Build Coastguard Worker absolute_datetime->meridiem() == grammar::datetime::Meridiem_AM ? 0
182*993b0882SAndroid Build Coastguard Worker : 1);
183*993b0882SAndroid Build Coastguard Worker }
184*993b0882SAndroid Build Coastguard Worker if (absolute_datetime->time_zone()) {
185*993b0882SAndroid Build Coastguard Worker datetime_parsed_data->SetAbsoluteValue(
186*993b0882SAndroid Build Coastguard Worker DatetimeComponent::ComponentType::ZONE_OFFSET,
187*993b0882SAndroid Build Coastguard Worker absolute_datetime->time_zone()->utc_offset_mins());
188*993b0882SAndroid Build Coastguard Worker }
189*993b0882SAndroid Build Coastguard Worker }
190*993b0882SAndroid Build Coastguard Worker
FillRelativeDateTimeComponents(const grammar::datetime::RelativeDateTime * relative_datetime)191*993b0882SAndroid Build Coastguard Worker StatusOr<DatetimeParsedData> FillRelativeDateTimeComponents(
192*993b0882SAndroid Build Coastguard Worker const grammar::datetime::RelativeDateTime* relative_datetime) {
193*993b0882SAndroid Build Coastguard Worker DatetimeParsedData datetime_parsed_data;
194*993b0882SAndroid Build Coastguard Worker for (const RelativeDatetimeComponent* relative_component :
195*993b0882SAndroid Build Coastguard Worker *relative_datetime->relative_datetime_component()) {
196*993b0882SAndroid Build Coastguard Worker TC3_ASSIGN_OR_RETURN(const DatetimeComponent::ComponentType component_type,
197*993b0882SAndroid Build Coastguard Worker ToComponentType(relative_component->component_type()));
198*993b0882SAndroid Build Coastguard Worker datetime_parsed_data.SetRelativeCount(component_type,
199*993b0882SAndroid Build Coastguard Worker relative_component->value());
200*993b0882SAndroid Build Coastguard Worker TC3_ASSIGN_OR_RETURN(
201*993b0882SAndroid Build Coastguard Worker const DatetimeComponent::RelativeQualifier relative_qualifier,
202*993b0882SAndroid Build Coastguard Worker ToRelativeQualifier(relative_component->modifier()));
203*993b0882SAndroid Build Coastguard Worker datetime_parsed_data.SetRelativeValue(component_type, relative_qualifier);
204*993b0882SAndroid Build Coastguard Worker }
205*993b0882SAndroid Build Coastguard Worker if (relative_datetime->base()) {
206*993b0882SAndroid Build Coastguard Worker FillAbsoluteDateTimeComponents(relative_datetime->base(),
207*993b0882SAndroid Build Coastguard Worker &datetime_parsed_data);
208*993b0882SAndroid Build Coastguard Worker }
209*993b0882SAndroid Build Coastguard Worker return datetime_parsed_data;
210*993b0882SAndroid Build Coastguard Worker }
211*993b0882SAndroid Build Coastguard Worker
212*993b0882SAndroid Build Coastguard Worker } // namespace
213*993b0882SAndroid Build Coastguard Worker
DatetimeGrounder(const CalendarLib * calendarlib)214*993b0882SAndroid Build Coastguard Worker DatetimeGrounder::DatetimeGrounder(const CalendarLib* calendarlib)
215*993b0882SAndroid Build Coastguard Worker : calendarlib_(*calendarlib) {}
216*993b0882SAndroid Build Coastguard Worker
Ground(const int64 reference_time_ms_utc,const std::string & reference_timezone,const std::string & reference_locale,const grammar::datetime::UngroundedDatetime * ungrounded_datetime) const217*993b0882SAndroid Build Coastguard Worker StatusOr<std::vector<DatetimeParseResult>> DatetimeGrounder::Ground(
218*993b0882SAndroid Build Coastguard Worker const int64 reference_time_ms_utc, const std::string& reference_timezone,
219*993b0882SAndroid Build Coastguard Worker const std::string& reference_locale,
220*993b0882SAndroid Build Coastguard Worker const grammar::datetime::UngroundedDatetime* ungrounded_datetime) const {
221*993b0882SAndroid Build Coastguard Worker DatetimeParsedData datetime_parsed_data;
222*993b0882SAndroid Build Coastguard Worker if (ungrounded_datetime->absolute_datetime()) {
223*993b0882SAndroid Build Coastguard Worker FillAbsoluteDateTimeComponents(ungrounded_datetime->absolute_datetime(),
224*993b0882SAndroid Build Coastguard Worker &datetime_parsed_data);
225*993b0882SAndroid Build Coastguard Worker } else if (ungrounded_datetime->relative_datetime()) {
226*993b0882SAndroid Build Coastguard Worker TC3_ASSIGN_OR_RETURN(datetime_parsed_data,
227*993b0882SAndroid Build Coastguard Worker FillRelativeDateTimeComponents(
228*993b0882SAndroid Build Coastguard Worker ungrounded_datetime->relative_datetime()));
229*993b0882SAndroid Build Coastguard Worker }
230*993b0882SAndroid Build Coastguard Worker std::vector<DatetimeParsedData> interpretations;
231*993b0882SAndroid Build Coastguard Worker FillInterpretations(datetime_parsed_data,
232*993b0882SAndroid Build Coastguard Worker calendarlib_.GetGranularity(datetime_parsed_data),
233*993b0882SAndroid Build Coastguard Worker &interpretations);
234*993b0882SAndroid Build Coastguard Worker std::vector<DatetimeParseResult> datetime_parse_result;
235*993b0882SAndroid Build Coastguard Worker
236*993b0882SAndroid Build Coastguard Worker for (const DatetimeParsedData& interpretation : interpretations) {
237*993b0882SAndroid Build Coastguard Worker std::vector<DatetimeComponent> date_components;
238*993b0882SAndroid Build Coastguard Worker interpretation.GetDatetimeComponents(&date_components);
239*993b0882SAndroid Build Coastguard Worker DatetimeParseResult result;
240*993b0882SAndroid Build Coastguard Worker // Text classifier only provides ambiguity limited to “AM/PM” which is
241*993b0882SAndroid Build Coastguard Worker // encoded in the pair of DatetimeParseResult; both corresponding to the
242*993b0882SAndroid Build Coastguard Worker // same date, but one corresponding to “AM” and the other one corresponding
243*993b0882SAndroid Build Coastguard Worker // to “PM”.
244*993b0882SAndroid Build Coastguard Worker if (!calendarlib_.InterpretParseData(
245*993b0882SAndroid Build Coastguard Worker interpretation, reference_time_ms_utc, reference_timezone,
246*993b0882SAndroid Build Coastguard Worker reference_locale, /*prefer_future_for_unspecified_date=*/true,
247*993b0882SAndroid Build Coastguard Worker &(result.time_ms_utc), &(result.granularity))) {
248*993b0882SAndroid Build Coastguard Worker return Status(
249*993b0882SAndroid Build Coastguard Worker StatusCode::INTERNAL,
250*993b0882SAndroid Build Coastguard Worker "Couldn't parse the UngroundedDatetime to DatetimeParseResult.");
251*993b0882SAndroid Build Coastguard Worker }
252*993b0882SAndroid Build Coastguard Worker
253*993b0882SAndroid Build Coastguard Worker // Sort the date time units by component type.
254*993b0882SAndroid Build Coastguard Worker std::stable_sort(date_components.begin(), date_components.end(),
255*993b0882SAndroid Build Coastguard Worker [](DatetimeComponent a, DatetimeComponent b) {
256*993b0882SAndroid Build Coastguard Worker return a.component_type > b.component_type;
257*993b0882SAndroid Build Coastguard Worker });
258*993b0882SAndroid Build Coastguard Worker result.datetime_components.swap(date_components);
259*993b0882SAndroid Build Coastguard Worker datetime_parse_result.push_back(result);
260*993b0882SAndroid Build Coastguard Worker }
261*993b0882SAndroid Build Coastguard Worker return datetime_parse_result;
262*993b0882SAndroid Build Coastguard Worker }
263*993b0882SAndroid Build Coastguard Worker
IsValidUngroundedDatetime(const UngroundedDatetime * ungrounded_datetime) const264*993b0882SAndroid Build Coastguard Worker bool DatetimeGrounder::IsValidUngroundedDatetime(
265*993b0882SAndroid Build Coastguard Worker const UngroundedDatetime* ungrounded_datetime) const {
266*993b0882SAndroid Build Coastguard Worker if (ungrounded_datetime->absolute_datetime()) {
267*993b0882SAndroid Build Coastguard Worker return IsValidDatetime(ungrounded_datetime->absolute_datetime());
268*993b0882SAndroid Build Coastguard Worker } else if (ungrounded_datetime->relative_datetime()) {
269*993b0882SAndroid Build Coastguard Worker return IsValidDatetime(ungrounded_datetime->relative_datetime());
270*993b0882SAndroid Build Coastguard Worker }
271*993b0882SAndroid Build Coastguard Worker return false;
272*993b0882SAndroid Build Coastguard Worker }
273*993b0882SAndroid Build Coastguard Worker
274*993b0882SAndroid Build Coastguard Worker } // namespace libtextclassifier3
275