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