• 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 "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