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