1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "date_time_filter.h"
16 #include <algorithm>
17 #include "i18n_hilog.h"
18 #include "utils.h"
19
20 namespace OHOS {
21 namespace Global {
22 namespace I18n {
DateTimeFilter(std::string & locale,DateTimeRule * dateTimeRule)23 DateTimeFilter::DateTimeFilter(std::string& locale, DateTimeRule* dateTimeRule)
24 {
25 this->locale = locale;
26 this->dateTimeRule = dateTimeRule;
27 }
28
~DateTimeFilter()29 DateTimeFilter::~DateTimeFilter()
30 {
31 }
32
33 // type of the time calculated based on the rule number.
GetType(std::string & name)34 int DateTimeFilter::GetType(std::string& name)
35 {
36 int32_t status = 0;
37 int key = ConvertString2Int(name, status);
38 if (status == -1) {
39 HILOG_ERROR_I18N("DateTimeFilter::GetType: convert %{public}s to Int failed.", name.c_str());
40 return FilterType::TYPE_NULL;
41 }
42 int type;
43 // 19999 and 30000 are the matching rule numbers.
44 if (key > 19999 && key < 30000) {
45 // 20009, 20011 and 21026 are the TYPE_WEEK rule numbers.
46 if (key == 20009 || key == 20011 || key == 21026) {
47 type = FilterType::TYPE_WEEK;
48 // 20010 is the TYPE_TODAY rule numbers.
49 } else if (key == 20010) {
50 type = FilterType::TYPE_TODAY;
51 } else {
52 type = FilterType::TYPE_DATE;
53 }
54 // 29999 - 40000 is the range of the rule number for TYPE_TIME.
55 } else if (key > 29999 && key < 40000) {
56 type = FilterType::TYPE_TIME;
57 // 9999 - 20000 is the range of the rule number for TYPE_DATETIME.
58 } else if (key > 9999 && key < 20000) {
59 type = FilterType::TYPE_DATETIME;
60 } else {
61 type = FilterType::TYPE_TIME_PERIOD;
62 }
63 return type;
64 }
65
Filter(icu::UnicodeString & content,std::vector<MatchedDateTimeInfo> & matches,std::vector<MatchedDateTimeInfo> & clearMatches,std::vector<MatchedDateTimeInfo> & pastMatches)66 std::vector<MatchedDateTimeInfo> DateTimeFilter::Filter(icu::UnicodeString& content,
67 std::vector<MatchedDateTimeInfo>& matches, std::vector<MatchedDateTimeInfo>& clearMatches,
68 std::vector<MatchedDateTimeInfo>& pastMatches)
69 {
70 matches = FilterOverlay(matches);
71 matches = FilterDatePeriod(content, matches);
72 matches = FilterByRules(content, matches, clearMatches);
73 matches = FilterByPast(content, matches, pastMatches);
74 return matches;
75 }
76
FilterOverlay(std::vector<MatchedDateTimeInfo> & matches)77 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterOverlay(std::vector<MatchedDateTimeInfo>& matches)
78 {
79 if (matches.size() == 0) {
80 return matches;
81 }
82 matches = FilterOverlayFirst(matches);
83 matches = FilterOverlaySecond(matches);
84 std::sort(matches.begin(), matches.end());
85 return matches;
86 }
87
88 // filtering results based on the clear rule.
FilterByRules(icu::UnicodeString & content,std::vector<MatchedDateTimeInfo> & matches,std::vector<MatchedDateTimeInfo> & clears)89 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterByRules(icu::UnicodeString& content,
90 std::vector<MatchedDateTimeInfo>& matches, std::vector<MatchedDateTimeInfo>& clears)
91 {
92 if (clears.size() == 0) {
93 return matches;
94 }
95 auto matchIterator = matches.begin();
96 while (matchIterator != matches.end()) {
97 MatchedDateTimeInfo match = (*matchIterator);
98 bool isDelete = false;
99 for (auto& clearMatch : clears) {
100 // remove the time within the filter range.
101 if (match.GetBegin() >= clearMatch.GetBegin() && match.GetEnd() <= clearMatch.GetEnd()) {
102 matchIterator = matches.erase(matchIterator);
103 isDelete = true;
104 break;
105 }
106 }
107 if (!isDelete) {
108 matchIterator++;
109 }
110 }
111 return matches;
112 }
113
114 // filtering results based on the past rule.
FilterByPast(icu::UnicodeString & content,std::vector<MatchedDateTimeInfo> & matches,std::vector<MatchedDateTimeInfo> & pasts)115 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterByPast(icu::UnicodeString& content,
116 std::vector<MatchedDateTimeInfo>& matches, std::vector<MatchedDateTimeInfo>& pasts)
117 {
118 if (pasts.size() == 0) {
119 return matches;
120 }
121 int32_t status = 0;
122 for (auto& pastMatch : pasts) {
123 std::string name = pastMatch.GetRegex();
124 int key = ConvertString2Int(name, status);
125 auto matchIterator = matches.begin();
126 while (matchIterator != matches.end()) {
127 MatchedDateTimeInfo match = (*matchIterator);
128 // fields with number < 200 are placed before the time.
129 if ((key < 200 && pastMatch.GetEnd() == match.GetBegin()) ||
130 // fields with number >= 200 are placed after the time.
131 (key >= 200 && pastMatch.GetBegin() == match.GetEnd())) {
132 matchIterator = matches.erase(matchIterator);
133 break;
134 }
135 matchIterator++;
136 }
137 }
138 return matches;
139 }
140
FilterOverlayFirst(std::vector<MatchedDateTimeInfo> & matches)141 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterOverlayFirst(std::vector<MatchedDateTimeInfo>& matches)
142 {
143 std::vector<MatchedDateTimeInfo> matchList;
144 for (MatchedDateTimeInfo& match : matches) {
145 bool valid = true;
146 auto matchIterator = matchList.begin();
147 while (matchIterator != matchList.end()) {
148 MatchedDateTimeInfo currentMatch = (*matchIterator);
149 if (!(currentMatch.GetBegin() == match.GetBegin() && currentMatch.GetEnd() == match.GetEnd()) &&
150 !(currentMatch.GetBegin() < match.GetBegin() && match.GetBegin() < currentMatch.GetEnd() &&
151 currentMatch.GetEnd() < match.GetEnd()) && !(match.GetBegin() < currentMatch.GetBegin() &&
152 currentMatch.GetBegin() < match.GetEnd() && match.GetEnd() < currentMatch.GetEnd())) {
153 matchIterator++;
154 continue;
155 }
156 std::string currentRegex = currentMatch.GetRegex();
157 std::string matchRegex = match.GetRegex();
158 if (this->dateTimeRule == nullptr) {
159 HILOG_ERROR_I18N("FilterOverlayFirst failed because this->dateTimeRule is nullptr.");
160 return matchList;
161 }
162 // if the matched time segments overlap, retain the high-priority.
163 if (this->dateTimeRule->CompareLevel(currentRegex, matchRegex) > -1) {
164 valid = false;
165 matchIterator++;
166 } else {
167 matchIterator = matchList.erase(matchIterator);
168 }
169 }
170 if (valid) {
171 matchList.push_back(match);
172 }
173 }
174 return matchList;
175 }
176
FilterOverlaySecond(std::vector<MatchedDateTimeInfo> & matches)177 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterOverlaySecond(std::vector<MatchedDateTimeInfo>& matches)
178 {
179 std::vector<MatchedDateTimeInfo> matchList;
180 for (MatchedDateTimeInfo& match : matches) {
181 bool valid = true;
182 auto matchIterator = matchList.begin();
183 while (matchIterator != matchList.end()) {
184 MatchedDateTimeInfo currentMatch = (*matchIterator);
185 // if one time within another time, the larger one is retained.
186 if ((currentMatch.GetBegin() > match.GetBegin() && currentMatch.GetEnd() <= match.GetEnd()) ||
187 (currentMatch.GetBegin() == match.GetBegin() && currentMatch.GetEnd() < match.GetEnd())) {
188 matchIterator = matchList.erase(matchIterator);
189 continue;
190 } else if (currentMatch.GetBegin() <= match.GetBegin() && currentMatch.GetEnd() >= match.GetEnd()) {
191 valid = false;
192 matchIterator++;
193 continue;
194 } else {
195 matchIterator++;
196 continue;
197 }
198 }
199 if (valid) {
200 matchList.push_back(match);
201 }
202 }
203 return matchList;
204 }
205
FilterDatePeriod(icu::UnicodeString & content,std::vector<MatchedDateTimeInfo> & matches)206 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterDatePeriod(icu::UnicodeString& content,
207 std::vector<MatchedDateTimeInfo>& matches)
208 {
209 std::vector<MatchedDateTimeInfo> matchList = matches;
210 matchList = FilterDate(content, matchList);
211 matchList = FilterDateTime(content, matchList);
212 matchList = FilterPeriod(content, matchList);
213 matchList = FilterDateTimePunc(content, matchList);
214 return matchList;
215 }
216
FilterDate(icu::UnicodeString & content,std::vector<MatchedDateTimeInfo> & matches)217 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterDate(icu::UnicodeString& content,
218 std::vector<MatchedDateTimeInfo>& matches)
219 {
220 std::vector<MatchedDateTimeInfo> result;
221 size_t lengthMatches = matches.size();
222 unsigned int arrayIndexLessValue = 1;
223 for (size_t i = 0; i < lengthMatches; i++) {
224 MatchedDateTimeInfo match = matches[i];
225 std::string matchRegex = match.GetRegex();
226 int type = GetType(matchRegex);
227 match.SetType(type);
228 if (type != FilterType::TYPE_DATE && type != FilterType::TYPE_TODAY && type != FilterType::TYPE_WEEK) {
229 result.push_back(match);
230 continue;
231 }
232 size_t hasNum = matches.size() - arrayIndexLessValue - i;
233 std::vector<MatchedDateTimeInfo> sub;
234 if (hasNum > 1) {
235 // 1 and 3 indicate the relative positions of the intercepted matches.
236 sub.assign(matches.begin() + i + 1, matches.begin() + i + 3);
237 } else if (hasNum == 1) {
238 // 1 and 2 indicate the relative positions of the intercepted matches.
239 sub.assign(matches.begin() + i + 1, matches.begin() + i + 2);
240 }
241 if (hasNum == 0 || sub.size() == 0) {
242 match.SetType(FilterType::TYPE_DATE);
243 result.push_back(match);
244 continue;
245 }
246 int status = NestDealDate(content, match, sub, -1);
247 match.SetType(FilterType::TYPE_DATE);
248 if (status == DateCombine::NOT_COMBINE) {
249 result.push_back(match);
250 continue;
251 } else if (status == DateCombine::TWO_COMBINE) {
252 i++;
253 } else {
254 // 2 indicates that the subsequent two time points and the current time point can be combined.
255 i = i + 2;
256 }
257 DealMatchE(content, matches[i], match);
258 result.push_back(match);
259 }
260 return result;
261 }
262
263 // process time that can be merged
DealMatchE(icu::UnicodeString & content,MatchedDateTimeInfo & nextMatch,MatchedDateTimeInfo & match)264 void DateTimeFilter::DealMatchE(icu::UnicodeString& content, MatchedDateTimeInfo& nextMatch,
265 MatchedDateTimeInfo& match)
266 {
267 int add = 0;
268 int leftIndex = content.indexOf('(', match.GetEnd());
269 if (leftIndex != -1 && leftIndex < nextMatch.GetBegin()) {
270 int end = content.indexOf(')', nextMatch.GetEnd());
271 if (end != -1) {
272 icu::UnicodeString right = content.tempSubString(nextMatch.GetEnd(), end + 1 - nextMatch.GetEnd());
273 if (right.trim() == ')') {
274 add = end - nextMatch.GetEnd() + 1;
275 }
276 }
277 }
278 match.SetEnd(nextMatch.GetEnd() + add);
279 }
280
281 // process two times connected with keywords
FilterDateTime(icu::UnicodeString & content,std::vector<MatchedDateTimeInfo> & matches)282 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterDateTime(icu::UnicodeString& content,
283 std::vector<MatchedDateTimeInfo>& matches)
284 {
285 if (matches.size() == 0) {
286 return matches;
287 }
288 UErrorCode status = U_ZERO_ERROR;
289 icu::RegexPattern* pattern = dateTimeRule->GetPatternByKey("datetime");
290 if (pattern == nullptr) {
291 HILOG_ERROR_I18N("FilterDateTime failed because pattern is nullptr.");
292 return matches;
293 }
294 std::string::size_type matchIndex = 1;
295 std::string::size_type lastMatchIndex = 0;
296 while (matchIndex < matches.size()) {
297 bool isDelete = false;
298 MatchedDateTimeInfo match = matches[matchIndex];
299 MatchedDateTimeInfo lastMatch = matches[lastMatchIndex];
300 int lType = lastMatch.GetType();
301 int cType = match.GetType();
302 if ((lType == FilterType::TYPE_DATE && cType == FilterType::TYPE_TIME) ||
303 (lType == FilterType::TYPE_DATE && cType == FilterType::TYPE_TIME_PERIOD && match.IsTimePeriod()) ||
304 (lType == FilterType::TYPE_TIME && cType == FilterType::TYPE_DATE) ||
305 (lType == FilterType::TYPE_TIME_PERIOD && lastMatch.IsTimePeriod() && cType == FilterType::TYPE_DATE)) {
306 // truncate the substring between two times.
307 icu::UnicodeString joiner = content.tempSubString(lastMatch.GetEnd(),
308 match.GetBegin() - lastMatch.GetEnd());
309 icu::RegexMatcher* matcher = pattern->matcher(joiner, status);
310 if (matcher == nullptr) {
311 HILOG_ERROR_I18N("FilterDateTime failed because pattern matcher failed.");
312 return matches;
313 }
314 bool isJoiner = (joiner.trim().isEmpty()) ? true : matcher->matches(status);
315 // the substring meets the rule, the two times are combined.
316 if (isJoiner) {
317 matches[lastMatchIndex].SetEnd(match.GetEnd());
318 int lastType = ((lType == FilterType::TYPE_DATE && cType == FilterType::TYPE_TIME) ||
319 (lType == FilterType::TYPE_TIME && cType == FilterType::TYPE_DATE)) ?
320 FilterType::TYPE_DATETIME : FilterType::TYPE_TIME_PERIOD;
321 matches[lastMatchIndex].SetType(lastType);
322 matches.erase(matches.begin() + matchIndex);
323 isDelete = true;
324 } else {
325 isDelete = DealBrackets(content, matches, matchIndex, matches[lastMatchIndex], match);
326 }
327 delete matcher;
328 }
329 if (!isDelete) {
330 lastMatchIndex = matchIndex;
331 matchIndex++;
332 }
333 }
334 return matches;
335 }
336
337 // process the time period consisting of two times.
FilterPeriod(icu::UnicodeString & content,std::vector<MatchedDateTimeInfo> & matches)338 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterPeriod(icu::UnicodeString& content,
339 std::vector<MatchedDateTimeInfo>& matches)
340 {
341 if (matches.size() == 0) {
342 return matches;
343 }
344 UErrorCode status = U_ZERO_ERROR;
345 icu::RegexPattern* pattern = dateTimeRule->GetPatternByKey("period");
346 if (pattern == nullptr) {
347 HILOG_ERROR_I18N("FilterPeriod failed because pattern is nullptr.");
348 return matches;
349 }
350 std::string::size_type matchIndex = 1;
351 std::string::size_type currentMatchIndex = 0;
352 while (matchIndex < matches.size()) {
353 MatchedDateTimeInfo match = matches[matchIndex];
354 MatchedDateTimeInfo currentMatch = matches[currentMatchIndex];
355 int cType = currentMatch.GetType();
356 int nType = match.GetType();
357 if ((cType == nType && (cType == FilterType::TYPE_DATE || cType == FilterType::TYPE_TIME ||
358 cType == FilterType::TYPE_DATETIME)) || (cType == FilterType::TYPE_DATETIME &&
359 nType == FilterType::TYPE_TIME)) {
360 icu::UnicodeString matchContent = content.tempSubString(currentMatch.GetEnd(),
361 match.GetBegin() - currentMatch.GetEnd());
362 icu::RegexMatcher* matcher = pattern->matcher(matchContent, status);
363 if (matcher == nullptr) {
364 HILOG_ERROR_I18N("FilterPeriod failed because pattern matcher failed.");
365 return matches;
366 }
367 if (matcher->matches(status)) {
368 matches[currentMatchIndex].SetEnd(match.GetEnd());
369 matches[currentMatchIndex].SetType(FilterType::TYPE_TIME_PERIOD);
370 bool isTimePeriod = (cType == FilterType::TYPE_TIME)? true : false;
371 matches[currentMatchIndex].SetIsTimePeriod(isTimePeriod);
372 matches.erase(matches.begin() + matchIndex);
373 } else {
374 currentMatchIndex = matchIndex;
375 matchIndex++;
376 }
377 delete matcher;
378 } else {
379 currentMatchIndex = matchIndex;
380 matchIndex++;
381 }
382 }
383 return matches;
384 }
385
386 // process the time separated by punctuation
FilterDateTimePunc(icu::UnicodeString & content,std::vector<MatchedDateTimeInfo> & matches)387 std::vector<MatchedDateTimeInfo> DateTimeFilter::FilterDateTimePunc(icu::UnicodeString& content,
388 std::vector<MatchedDateTimeInfo>& matches)
389 {
390 if (matches.size() == 0) {
391 return matches;
392 }
393 std::string::size_type matchIndex = 1;
394 std::string::size_type currentMatchIndex = 0;
395 while (matchIndex < matches.size()) {
396 MatchedDateTimeInfo match = matches[matchIndex];
397 MatchedDateTimeInfo currentMatch = matches[currentMatchIndex];
398 int cType = currentMatch.GetType();
399 int lType = match.GetType();
400 if ((cType == FilterType::TYPE_DATE && lType == FilterType::TYPE_TIME) ||
401 (cType == FilterType::TYPE_DATE && lType == FilterType::TYPE_TIME_PERIOD && match.IsTimePeriod()) ||
402 (cType == FilterType::TYPE_TIME && lType == FilterType::TYPE_DATE) ||
403 (cType == FilterType::TYPE_TIME_PERIOD && currentMatch.IsTimePeriod() && lType == FilterType::TYPE_DATE)) {
404 bool isPunc = false;
405 icu::UnicodeString ss = content.tempSubString(currentMatch.GetEnd(),
406 match.GetBegin() - currentMatch.GetEnd());
407 if (ss.trim() == ',' || ss.trim() == ",") {
408 isPunc = true;
409 }
410 if (isPunc) {
411 matches[currentMatchIndex].SetEnd(match.GetEnd());
412 int currentType = ((cType == FilterType::TYPE_DATE && lType == FilterType::TYPE_TIME) ||
413 cType == FilterType::TYPE_TIME) ? FilterType::TYPE_DATETIME : FilterType::TYPE_TIME_PERIOD;
414 matches[currentMatchIndex].SetType(currentType);
415 matches.erase(matches.begin() + matchIndex);
416 } else {
417 currentMatchIndex = matchIndex;
418 matchIndex++;
419 }
420 } else {
421 currentMatchIndex = matchIndex;
422 matchIndex++;
423 }
424 }
425 return matches;
426 }
427
DealBrackets(icu::UnicodeString & content,std::vector<MatchedDateTimeInfo> & matches,int matchIndex,MatchedDateTimeInfo & lastMatch,MatchedDateTimeInfo & currentMatch)428 bool DateTimeFilter::DealBrackets(icu::UnicodeString& content, std::vector<MatchedDateTimeInfo>& matches,
429 int matchIndex, MatchedDateTimeInfo& lastMatch, MatchedDateTimeInfo& currentMatch)
430 {
431 int lType = lastMatch.GetType();
432 int cType = currentMatch.GetType();
433 if (lType == FilterType::TYPE_TIME) {
434 int add = 0;
435 icu::UnicodeString endStr = content.tempSubString(lastMatch.GetEnd());
436 UErrorCode status = U_ZERO_ERROR;
437 icu::RegexPattern* pattern = dateTimeRule->GetPatternByKey("brackets");
438 if (pattern == nullptr) {
439 HILOG_ERROR_I18N("DealBrackets failed because pattern is nullptr.");
440 return false;
441 }
442 icu::RegexMatcher* matcher = pattern->matcher(endStr, status);
443 if (matcher == nullptr) {
444 HILOG_ERROR_I18N("DealBrackets failed because pattern matcher failed.");
445 return false;
446 }
447 icu::UnicodeString groupStr;
448 if (matcher->find(status)) {
449 groupStr = matcher->group(1, status);
450 add = matcher->group(status).length();
451 }
452 delete matcher;
453 if (!groupStr.isEmpty() && groupStr.trim() == content.tempSubString(currentMatch.GetBegin(),
454 currentMatch.GetEnd() - currentMatch.GetBegin()).trim()) {
455 lastMatch.SetEnd(lastMatch.GetEnd() + add);
456 lastMatch.SetType(FilterType::TYPE_DATETIME);
457 matches.erase(matches.begin() + matchIndex);
458 return true;
459 }
460 } else if (lType == FilterType::TYPE_DATE && cType == FilterType::TYPE_TIME) {
461 icu::UnicodeString beginStr = content.tempSubString(0, lastMatch.GetBegin());
462 icu::UnicodeString endStr = content.tempSubString(lastMatch.GetEnd(),
463 currentMatch.GetBegin() - lastMatch.GetEnd());
464 if (beginStr.trim().endsWith('(') && endStr.trim() == ')') {
465 int bracketLastIndex = beginStr.lastIndexOf('(');
466 lastMatch.SetBegin(bracketLastIndex);
467 lastMatch.SetEnd(currentMatch.GetEnd());
468 lastMatch.SetType(FilterType::TYPE_DATETIME);
469 matches.erase(matches.begin() + matchIndex);
470 return true;
471 }
472 }
473 return false;
474 }
475
NestDealDate(icu::UnicodeString & content,MatchedDateTimeInfo & current,std::vector<MatchedDateTimeInfo> & matches,int preType)476 int DateTimeFilter::NestDealDate(icu::UnicodeString& content, MatchedDateTimeInfo& current,
477 std::vector<MatchedDateTimeInfo>& matches, int preType)
478 {
479 int result = 0;
480 MatchedDateTimeInfo nextMatch = matches[0];
481 std::string nextRegex = nextMatch.GetRegex();
482 int nextType = GetType(nextRegex);
483 if (nextType != FilterType::TYPE_DATE && nextType != FilterType::TYPE_TODAY && nextType != FilterType::TYPE_WEEK) {
484 return result;
485 }
486 std::string currentRegex = current.GetRegex();
487 if (nextType == GetType(currentRegex) || nextType == preType) {
488 return result;
489 }
490 result = GetResult(content, current, nextMatch, matches);
491 return result;
492 }
493
GetResult(icu::UnicodeString & content,MatchedDateTimeInfo & current,MatchedDateTimeInfo & nextMatch,std::vector<MatchedDateTimeInfo> & matches)494 int DateTimeFilter::GetResult(icu::UnicodeString& content, MatchedDateTimeInfo& current,
495 MatchedDateTimeInfo& nextMatch, std::vector<MatchedDateTimeInfo>& matches)
496 {
497 int result = 0;
498 icu::UnicodeString ss = content.tempSubString(current.GetEnd(), nextMatch.GetBegin() - current.GetEnd());
499 if (this->dateTimeRule == nullptr) {
500 HILOG_ERROR_I18N("GetResult failed because this->dateTimeRule is nullptr.");
501 return result;
502 }
503 if (this->dateTimeRule->IsRelDates(ss, this->locale) || ss.trim() == '(') {
504 bool isThree = false;
505 if (matches.size() > 1) {
506 std::vector<MatchedDateTimeInfo> nextMatches(matches.begin() + 1, matches.end());
507 int connect = NestDealDate(content, nextMatch, nextMatches, current.GetType());
508 if (connect == DateCombine::TWO_COMBINE) {
509 isThree = true;
510 }
511 }
512 bool isBrackets = false;
513 if (ss.trim() == '(') {
514 icu::UnicodeString endStr = content.tempSubString(current.GetEnd());
515 icu::RegexPattern* pattern = dateTimeRule->GetPatternByKey("brackets");
516 if (pattern == nullptr) {
517 HILOG_ERROR_I18N("GetResult failed because pattern is nullptr.");
518 return result;
519 }
520 UErrorCode status = U_ZERO_ERROR;
521 icu::RegexMatcher* matcher = pattern->matcher(endStr, status);
522 if (matcher == nullptr) {
523 HILOG_ERROR_I18N("GetResult failed because pattern matcher failed.");
524 return result;
525 }
526 icu::UnicodeString str = matcher->find(status) ? matcher->group(1, status) : "";
527 int end = isThree ? matches[1].GetEnd() : nextMatch.GetEnd();
528 if (!str.isEmpty() && str.trim() == content.tempSubString(nextMatch.GetBegin(),
529 end - nextMatch.GetBegin()).trim()) {
530 isBrackets = true;
531 }
532 delete matcher;
533 }
534 if (this->dateTimeRule->IsRelDates(ss, this->locale) || isBrackets) {
535 result = isThree ? DateCombine::ALL_COMBINE : DateCombine::TWO_COMBINE;
536 }
537 }
538 return result;
539 }
540 } // namespace I18n
541 } // namespace Global
542 } // namespace OHOS