• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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_format.h"
16 #include "i18n_hilog.h"
17 #include "locale_config.h"
18 #include "ohos/init_data.h"
19 #include "parameter.h"
20 #include "utils.h"
21 
22 namespace OHOS {
23 namespace Global {
24 namespace I18n {
25 const char* DateTimeFormat::DEVICE_TYPE_NAME = "const.product.devicetype";
26 static const std::string NUMERIC_STR = "numeric";
27 static const icu::UnicodeString YMD_SKELETON = "yyyyMd";
28 static const icu::UnicodeString YM_SKELETON = "yyyyM";
29 static const icu::UnicodeString MD_SKELETON = "Md";
30 static const icu::UnicodeString D_SKELETON = "d";
31 static const icu::UnicodeString DD_SKELETON = "dd";
32 static const icu::UnicodeString LTR_SYMBOL = "\u200e";
33 static const icu::UnicodeString RTL_SYMBOL = "\u200f";
34 static const size_t YMD_INDEX = 0;
35 static const size_t YM_INDEX = 1;
36 static const size_t MD_INDEX = 2;
37 static const double DEFAULT_TIME = 1752768000000;
38 
39 using namespace icu;
40 bool DateTimeFormat::icuInitialized = DateTimeFormat::Init();
41 
42 std::map<std::string, DateFormat::EStyle> DateTimeFormat::dateTimeStyle = {
43     { "full", DateFormat::EStyle::kFull },
44     { "long", DateFormat::EStyle::kLong },
45     { "medium", DateFormat::EStyle::kMedium },
46     { "short", DateFormat::EStyle::kShort }
47 };
48 
49 std::unordered_map<std::string, DateTimeFormat::DefaultStyle> DateTimeFormat::DeviceToStyle = {
50     { "tablet", DefaultStyle::LONG },
51     { "2in1", DefaultStyle::LONG },
52     { "tv", DefaultStyle::LONG },
53     { "pc", DefaultStyle::LONG },
54     { "liteWearable", DefaultStyle::SHORT },
55     { "wearable", DefaultStyle::SHORT },
56     { "watch", DefaultStyle::SHORT }
57 };
58 
59 std::unordered_map<DateTimeFormat::DefaultStyle, DateFormat::EStyle> DateTimeFormat::DefaultDTStyle = {
60     { DefaultStyle::LONG, DateFormat::EStyle::kMedium },
61     { DefaultStyle::DEFAULT, DateFormat::EStyle::kShort },
62     { DefaultStyle::SHORT, DateFormat::EStyle::kShort },
63 };
64 
65 std::map<icu::UnicodeString, std::string> PATTERN_TO_EXT_PARAM = {
66     { "d/MM/y", "0001" },
67     { "d/M/yy", "0002" },
68     { "y-MM-d", "0003" },
69     { "d/M/y", "0004" },
70     { "d/MM/yy", "0005" },
71     { "d.MM.yy", "0006" },
72     { "yy/MM/d", "0007" },
73     { "d.MM.y", "0008" },
74     { "d-MM-y", "0009" },
75     { "y/M/d", "0010" },
76     { "d-M-y", "0011" },
77 };
78 
79 std::unordered_map<std::string, std::vector<icu::UnicodeString>> EXT_PARAM_TO_PATTERNS = {
80     { "0001", { "d/MM/y", "MM/y", "d/MM" } },
81     { "0002", { "d/M/yy", "M/yy", "d/M" } },
82     { "0003", { "y-MM-d", "y-MM", "MM-d" } },
83     { "0004", { "d/M/y", "M/y", "d/M" } },
84     { "0005", { "d/MM/yy", "MM/yy", "d/MM" } },
85     { "0006", { "d.MM.yy", "MM.yy", "d.MM" } },
86     { "0007", { "yy/MM/d", "yy/MM", "MM/d" } },
87     { "0008", { "d.MM.y", "MM.y", "d.MM" } },
88     { "0009", { "d-MM-y", "MM-y", "d-MM" } },
89     { "0010", { "y/M/d", "y/M", "M/d" } },
90     { "0011", { "d-M-y", "M-y", "d-M" } },
91 };
92 
DateTimeFormat(const std::vector<std::string> & localeTags,std::map<std::string,std::string> & configs)93 DateTimeFormat::DateTimeFormat(const std::vector<std::string> &localeTags, std::map<std::string, std::string> &configs)
94 {
95     defaultStyle = GetDefaultStyle();
96     ParseConfigsPartOne(configs);
97     ParseConfigsPartTwo(configs);
98     for (size_t i = 0; i < localeTags.size(); i++) {
99         std::string curLocale = localeTags[i];
100         UErrorCode status = U_ZERO_ERROR;
101         locale = Locale::forLanguageTag(StringPiece(curLocale), status);
102         if (U_FAILURE(status)) {
103             continue;
104         }
105         if (LocaleInfo::allValidLocales.count(locale.getLanguage()) > 0) {
106             finalLocale = curLocale;
107             break;
108         }
109     }
110     if (finalLocale.empty()) {
111         finalLocale = LocaleConfig::GetEffectiveLocale();
112     }
113     std::string localeWithoutCustExtParam = LocaleConfig::RemoveCustExtParam(finalLocale);
114     createSuccess = InitWithLocale(localeWithoutCustExtParam, configs);
115     if (!createSuccess) {
116         HILOG_ERROR_I18N("DateTimeFormat::DateTimeFormat: Init dateTimeFormat failed.");
117     }
118 }
119 
~DateTimeFormat()120 DateTimeFormat::~DateTimeFormat()
121 {
122 }
123 
CheckInitSuccess()124 bool DateTimeFormat::CheckInitSuccess()
125 {
126     return (dateIntvFormat == nullptr || calendar == nullptr || dateFormat == nullptr || localeInfo == nullptr) ?
127         false : true;
128 }
129 
CreateInstance(const std::vector<std::string> & localeTags,std::map<std::string,std::string> & configs)130 std::unique_ptr<DateTimeFormat> DateTimeFormat::CreateInstance(const std::vector<std::string> &localeTags,
131                                                                std::map<std::string, std::string> &configs)
132 {
133     std::unique_ptr<DateTimeFormat> dateTimeFormat = std::make_unique<DateTimeFormat>(localeTags, configs);
134     if (dateTimeFormat == nullptr || !dateTimeFormat->CheckInitSuccess()) {
135         return nullptr;
136     }
137     return dateTimeFormat;
138 }
139 
InitWithLocale(const std::string & curLocale,std::map<std::string,std::string> & configs)140 bool DateTimeFormat::InitWithLocale(const std::string &curLocale, std::map<std::string, std::string> &configs)
141 {
142     localeInfo = std::make_unique<LocaleInfo>(curLocale, configs);
143     if (localeInfo == nullptr || !localeInfo->InitSuccess()) {
144         return false;
145     }
146     locale = localeInfo->GetLocale();
147     localeTag = localeInfo->GetBaseName();
148     if (hourCycle.empty()) {
149         hourCycle = localeInfo->GetHourCycle();
150     }
151     if (hour12.empty() && hourCycle.empty() && !LocaleConfig::IsEmpty24HourClock()) {
152         bool is24HourClock = LocaleConfig::Is24HourClock();
153         hour12 = is24HourClock ? "false" : "true";
154     }
155     ComputeHourCycleChars();
156     ComputeSkeleton();
157     UErrorCode status = U_ZERO_ERROR;
158     if (!configs.size()) {
159         InitDateFormatWithoutConfigs(status);
160     } else {
161         InitDateFormat(status);
162     }
163     if (U_FAILURE(status)) {
164         HILOG_ERROR_I18N("DateTimeFormat::InitWithLocale: InitDateFormat failed.");
165         return false;
166     }
167     status = U_ZERO_ERROR;
168     calendar = std::unique_ptr<icu::Calendar>(Calendar::createInstance(locale, status));
169     if (U_FAILURE(status)) {
170         HILOG_ERROR_I18N("DateTimeFormat::InitWithLocale: Create calendar instance failed.");
171         return false;
172     }
173     return true;
174 }
175 
InitDateFormatWithoutConfigs(UErrorCode & status)176 void DateTimeFormat::InitDateFormatWithoutConfigs(UErrorCode &status)
177 {
178     DateFormat::EStyle style = DefaultDTStyle[defaultStyle];
179     if (style == DateFormat::EStyle::kShort) {
180         std::string number = LocaleConfig::GetPatternNumberFromLocale(finalLocale);
181         auto iter = EXT_PARAM_TO_PATTERNS.find(number);
182         if (iter != EXT_PARAM_TO_PATTERNS.end()) {
183             pattern = iter->second[YMD_INDEX];
184             icu::UnicodeString dayPattern = GetDayPatternFromLocale(finalLocale);
185             pattern.findAndReplace(D_SKELETON, dayPattern);
186         } else {
187             pattern = DateTimeFormat::GetPatternFromLocale(finalLocale);
188         }
189         if (InitFormatter()) {
190             return;
191         }
192     }
193     dateFormat = std::unique_ptr<icu::DateFormat>(DateFormat::createDateInstance(style, locale));
194     SimpleDateFormat *simDateFormat = static_cast<SimpleDateFormat*>(dateFormat.get());
195     if (simDateFormat != nullptr) {
196         simDateFormat->toPattern(pattern);
197     }
198     dateIntvFormat =
199         std::unique_ptr<DateIntervalFormat>(DateIntervalFormat::createInstance(pattern, locale, status));
200 }
201 
FixPatternPartOne()202 void DateTimeFormat::FixPatternPartOne()
203 {
204     if (hour12 == "true") {
205         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("H")),
206             icu::UnicodeString::fromUTF8(StringPiece("h")));
207         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
208             icu::UnicodeString::fromUTF8(StringPiece("h")));
209         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
210             icu::UnicodeString::fromUTF8(StringPiece("h")));
211     } else if (hour12 == "false") {
212         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("h")),
213             icu::UnicodeString::fromUTF8(StringPiece("H")));
214         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
215             icu::UnicodeString::fromUTF8(StringPiece("H")));
216         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
217             icu::UnicodeString::fromUTF8(StringPiece("H")));
218         RemoveAmPmChar();
219     } else if (hourCycle != "") {
220         FixPatternPartTwo();
221     }
222 }
223 
FixPatternPartTwo()224 void DateTimeFormat::FixPatternPartTwo()
225 {
226     if (hourCycle == "h11") {
227         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("h")),
228             icu::UnicodeString::fromUTF8(StringPiece("k")));
229         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("H")),
230             icu::UnicodeString::fromUTF8(StringPiece("k")));
231         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
232             icu::UnicodeString::fromUTF8(StringPiece("k")));
233     } else if (hourCycle == "h12") {
234         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("H")),
235             icu::UnicodeString::fromUTF8(StringPiece("h")));
236         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
237             icu::UnicodeString::fromUTF8(StringPiece("h")));
238         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
239             icu::UnicodeString::fromUTF8(StringPiece("h")));
240     } else if (hourCycle == "h23") {
241         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("h")),
242             icu::UnicodeString::fromUTF8(StringPiece("K")));
243         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("H")),
244             icu::UnicodeString::fromUTF8(StringPiece("K")));
245         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
246             icu::UnicodeString::fromUTF8(StringPiece("K")));
247         RemoveAmPmChar();
248     } else if (hourCycle == "h24") {
249         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("h")),
250             icu::UnicodeString::fromUTF8(StringPiece("H")));
251         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
252             icu::UnicodeString::fromUTF8(StringPiece("H")));
253         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
254             icu::UnicodeString::fromUTF8(StringPiece("H")));
255         RemoveAmPmChar();
256     }
257 }
258 
RemoveAmPmChar()259 void DateTimeFormat::RemoveAmPmChar()
260 {
261     std::string patternString = "";
262     pattern.toUTF8String(patternString);
263     size_t amPmCharStartIdx = 0;
264     size_t amPmCharEndIdx = 0;
265     for (size_t i = 0; i < patternString.length(); i++) {
266         if (patternString[i] != 'a') {
267             continue;
268         }
269         if ((i + 1) < patternString.length() && patternString[i + 1] == 't') {
270             continue;
271         }
272         if (!i) {
273             amPmCharStartIdx = i;
274         } else {
275             amPmCharStartIdx = i - 1;
276             while (amPmCharStartIdx > 0 && patternString[amPmCharStartIdx] == ' ') {
277                 amPmCharStartIdx -= 1;
278             }
279             if (amPmCharStartIdx || patternString[amPmCharStartIdx] != ' ') {
280                 amPmCharStartIdx += 1;
281             }
282         }
283         amPmCharEndIdx = i + 1;
284         while (amPmCharEndIdx < patternString.length() && patternString[amPmCharEndIdx] == ' ') {
285             amPmCharEndIdx += 1;
286         }
287         break;
288     }
289     size_t length = amPmCharEndIdx - amPmCharStartIdx;
290     if (length) {
291         if (!amPmCharStartIdx || amPmCharEndIdx == patternString.length()) {
292             patternString = patternString.replace(amPmCharStartIdx, length, "");
293         } else {
294             patternString = patternString.replace(amPmCharStartIdx, length, " ");
295         }
296         pattern = icu::UnicodeString(patternString.data(), patternString.length());
297     }
298 }
299 
InitDateFormat(UErrorCode & status)300 void DateTimeFormat::InitDateFormat(UErrorCode &status)
301 {
302     if (!dateStyle.empty() || !timeStyle.empty()) {
303         bool initSuccess = false;
304         InitDateFormatWithDateTimeStyle(initSuccess, status);
305         if (initSuccess) {
306             return;
307         }
308         dateFormat = std::make_unique<SimpleDateFormat>(pattern, locale, status);
309         if (U_FAILURE(status)) {
310             HILOG_ERROR_I18N("DateTimeFormat::InitDateFormat: Create SimpleDateFormat instance failed.");
311             return;
312         }
313     } else {
314         auto patternGenerator =
315             std::unique_ptr<DateTimePatternGenerator>(DateTimePatternGenerator::createInstance(locale, status));
316         if (U_FAILURE(status) || patternGenerator == nullptr) {
317             HILOG_ERROR_I18N("DateTimeFormat::InitDateFormat: Create DateTimePatternGenerator instance failed.");
318             return;
319         }
320         ComputePattern();
321         pattern =
322             patternGenerator->replaceFieldTypes(patternGenerator->getBestPattern(pattern, status), pattern, status);
323         pattern = patternGenerator->getBestPattern(pattern, status);
324         SetDayPeriod();
325         if (DateTimeFormat::InitPatternByNumeric()) {
326             return;
327         }
328         status = U_ZERO_ERROR;
329         dateFormat = std::make_unique<SimpleDateFormat>(pattern, locale, status);
330         if (U_FAILURE(status)) {
331             HILOG_ERROR_I18N("DateTimeFormat::InitDateFormat: Create SimpleDateFormat object failed.");
332             return;
333         }
334     }
335     status = U_ZERO_ERROR;
336     dateIntvFormat =
337         std::unique_ptr<DateIntervalFormat>(DateIntervalFormat::createInstance(pattern, locale, status));
338 }
339 
InitDateFormatWithDateTimeStyle(bool & initSuccess,UErrorCode & status)340 void DateTimeFormat::InitDateFormatWithDateTimeStyle(bool& initSuccess, UErrorCode &status)
341 {
342     DateFormat::EStyle dateStyleValue = DateFormat::EStyle::kNone;
343     DateFormat::EStyle timeStyleValue = DateFormat::EStyle::kNone;
344     if (!dateStyle.empty()) {
345         if (dateTimeStyle.count(dateStyle) > 0) {
346             dateStyleValue = dateTimeStyle[dateStyle];
347         } else if (dateStyle == "auto") {
348             dateStyleValue = DefaultDTStyle[defaultStyle];
349         }
350     }
351     if (!timeStyle.empty()) {
352         if (dateTimeStyle.count(timeStyle) > 0) {
353             timeStyleValue = dateTimeStyle[timeStyle];
354         } else if (timeStyle == "auto") {
355             timeStyleValue = DefaultDTStyle[defaultStyle];
356         }
357     }
358     icu::DateFormat *tempDateFormat = DateFormat::createDateTimeInstance(dateStyleValue, timeStyleValue, locale);
359     if (tempDateFormat == nullptr) {
360         status = U_INVALID_FORMAT_ERROR;
361         HILOG_ERROR_I18N("DateTimeFormat::InitDateFormatWithDateTimeStyle: Create DateFormat instance failed.");
362         return;
363     }
364     SimpleDateFormat* simpleDateFormat = static_cast<SimpleDateFormat*>(tempDateFormat);
365     std::unique_ptr<SimpleDateFormat> simDateFormatPtr = std::unique_ptr<SimpleDateFormat>(simpleDateFormat);
366     if (simDateFormatPtr != nullptr) {
367         simDateFormatPtr->toPattern(pattern);
368     }
369     FixPatternPartOne();
370     if (dateStyleValue == DateFormat::EStyle::kShort) {
371         initSuccess = InitPatternByDateStyle();
372     }
373 }
374 
SetDayPeriod()375 void DateTimeFormat::SetDayPeriod()
376 {
377     if (dayPeriod == "short" || (dayPeriod == "auto" && defaultStyle ==  DefaultStyle::DEFAULT)) {
378         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("a")),
379             icu::UnicodeString::fromUTF8(StringPiece("B")));
380     } else if (dayPeriod == "long" || (dayPeriod == "auto" && defaultStyle ==  DefaultStyle::LONG)) {
381         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("a")),
382             icu::UnicodeString::fromUTF8(StringPiece("BBBB")));
383     } else if (dayPeriod == "narrow" || (dayPeriod == "auto" && defaultStyle ==  DefaultStyle::SHORT)) {
384         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("a")),
385             icu::UnicodeString::fromUTF8(StringPiece("BBBBB")));
386     }
387 }
388 
ParseConfigsPartOne(std::map<std::string,std::string> & configs)389 void DateTimeFormat::ParseConfigsPartOne(std::map<std::string, std::string> &configs)
390 {
391     if (configs.count("dateStyle") > 0) {
392         dateStyle = configs["dateStyle"];
393     }
394     if (configs.count("timeStyle") > 0) {
395         timeStyle = configs["timeStyle"];
396     }
397     if (configs.count("year") > 0) {
398         year = configs["year"];
399     }
400     if (configs.count("month") > 0) {
401         month = configs["month"];
402     }
403     if (configs.count("day") > 0) {
404         day = configs["day"];
405     }
406     if (configs.count("hour") > 0) {
407         hour = configs["hour"];
408     }
409     if (configs.count("minute") > 0) {
410         minute = configs["minute"];
411     }
412     if (configs.count("second") > 0) {
413         second = configs["second"];
414     }
415 }
416 
ParseConfigsPartTwo(std::map<std::string,std::string> & configs)417 void DateTimeFormat::ParseConfigsPartTwo(std::map<std::string, std::string> &configs)
418 {
419     if (configs.count("hourCycle") > 0) {
420         hourCycle = configs["hourCycle"];
421     }
422     if (configs.count("timeZone") > 0) {
423         timeZone = configs["timeZone"];
424     }
425     if (configs.count("numberingSystem") > 0) {
426         numberingSystem = configs["numberingSystem"];
427     }
428     if (configs.count("hour12") > 0) {
429         hour12 = configs["hour12"];
430     }
431     if (configs.count("weekday") > 0) {
432         weekday = configs["weekday"];
433     }
434     if (configs.count("era") > 0) {
435         era = configs["era"];
436     }
437     if (configs.count("timeZoneName") > 0) {
438         timeZoneName = configs["timeZoneName"];
439     }
440     if (configs.count("dayPeriod") > 0) {
441         dayPeriod = configs["dayPeriod"];
442     }
443     if (configs.count("localeMatcher") > 0) {
444         localeMatcher = configs["localeMatcher"];
445     }
446     if (configs.count("formatMatcher") > 0) {
447         formatMatcher = configs["formatMatcher"];
448     }
449 }
450 
ComputeSkeleton()451 void DateTimeFormat::ComputeSkeleton()
452 {
453     if (year.empty() && month.empty() && day.empty() && hour.empty() && minute.empty() && second.empty() &&
454         weekday.empty()) {
455         pattern.append("yMd");
456     }
457     AddOptions(year, yearChar);
458     AddOptions(month, monthChar);
459     AddOptions(day, dayChar);
460     AddOptions(hour, hourChar);
461     AddOptions(minute, minuteChar);
462     AddOptions(second, secondChar);
463     if ((hourCycle == "h12" || hourCycle == "h11" || hour12 == "true") && !hour.empty()) {
464         pattern.append(amPmChar);
465     }
466     AddOptions(timeZoneName, timeZoneChar);
467     AddOptions(weekday, weekdayChar);
468     AddOptions(era, eraChar);
469 }
470 
AddOptions(std::string option,char16_t optionChar)471 void DateTimeFormat::AddOptions(std::string option, char16_t optionChar)
472 {
473     if (!option.empty()) {
474         pattern.append(optionChar);
475     }
476 }
477 
ComputeHourCycleChars()478 void DateTimeFormat::ComputeHourCycleChars()
479 {
480     if (!hour12.empty()) {
481         if (hour12 == "true") {
482             hourNumericString = "h";
483             hourTwoDigitString = "hh";
484         } else {
485             hourNumericString = "H";
486             hourTwoDigitString = "HH";
487         }
488     } else {
489         if (hourCycle == "h11") {
490             hourNumericString = "K";
491             hourTwoDigitString = "KK";
492         } else if (hourCycle == "h12") {
493             hourNumericString = "h";
494             hourTwoDigitString = "hh";
495         } else if (hourCycle == "h23") {
496             hourNumericString = "H";
497             hourTwoDigitString = "HH";
498         } else if (hourCycle == "h24") {
499             hourNumericString = "k";
500             hourTwoDigitString = "kk";
501         }
502     }
503 }
504 
ComputePattern()505 void DateTimeFormat::ComputePattern()
506 {
507     ComputePartOfPattern(year, yearChar, "yy", "yyyy");
508     ComputePartOfPattern(day, dayChar, "dd", "d");
509     ComputePartOfPattern(hour, hourChar, hourTwoDigitString, hourNumericString);
510     ComputePartOfPattern(minute, minuteChar, "mm", "mm");
511     ComputePartOfPattern(second, secondChar, "ss", "ss");
512     if (!month.empty()) {
513         UnicodeString monthOfPattern = UnicodeString(monthChar);
514         int32_t length = monthOfPattern.length();
515         if (month == "numeric" && length != NUMERIC_LENGTH) {
516             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("M")));
517         } else if (month == "2-digit" && length != TWO_DIGIT_LENGTH) {
518             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("MM")));
519         } else if ((month == "long" && length != LONG_LENGTH) || (month == "auto" &&
520             defaultStyle ==  DefaultStyle::LONG)) {
521             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("MMMM")));
522         } else if ((month == "short" && length != SHORT_LENGTH) || (month == "auto" &&
523             (defaultStyle ==  DefaultStyle::DEFAULT || defaultStyle ==  DefaultStyle::SHORT))) {
524             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("MMM")));
525         } else if (month == "narrow" && length != NARROW_LENGTH) {
526             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("MMMMM")));
527         }
528     }
529 
530     ComputeTimeZoneOfPattern(timeZoneName, timeZoneChar, "zzzz", "O");
531     ComputeWeekdayOfPattern(weekday, weekdayChar, "EEEE", "E", "EEEEE");
532     ComputeEraOfPattern(era, eraChar, "GGGG", "G", "GGGGG");
533 }
534 
ComputePartOfPattern(std::string option,char16_t character,std::string twoDigitChar,std::string numericChar)535 void DateTimeFormat::ComputePartOfPattern(std::string option, char16_t character, std::string twoDigitChar,
536     std::string numericChar)
537 {
538     if (!option.empty()) {
539         UnicodeString curPartOfPattern = UnicodeString(character);
540         if (option == "2-digit") {
541             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(twoDigitChar)));
542         } else if (option == "numeric") {
543             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(numericChar)));
544         }
545     }
546 }
547 
ComputeTimeZoneOfPattern(std::string option,char16_t character,std::string longChar,std::string shortChar)548 void DateTimeFormat::ComputeTimeZoneOfPattern(std::string option, char16_t character, std::string longChar,
549     std::string shortChar)
550 {
551     if (!option.empty()) {
552         UnicodeString timeZoneOfPattern = UnicodeString(character);
553         if (option == "long" || (option == "auto" && defaultStyle ==  DefaultStyle::LONG)) {
554             pattern.findAndReplace(timeZoneOfPattern, UnicodeString::fromUTF8(StringPiece(longChar)));
555         } else if (option == "short" || (option == "auto" && (defaultStyle ==  DefaultStyle::DEFAULT ||
556             defaultStyle ==  DefaultStyle::SHORT))) {
557             pattern.findAndReplace(timeZoneOfPattern, UnicodeString::fromUTF8(StringPiece(shortChar)));
558         }
559     }
560 }
561 
ComputeWeekdayOfPattern(std::string option,char16_t character,std::string longChar,std::string shortChar,std::string narrowChar)562 void DateTimeFormat::ComputeWeekdayOfPattern(std::string option, char16_t character, std::string longChar,
563     std::string shortChar, std::string narrowChar)
564 {
565     if (!option.empty()) {
566         UnicodeString curPartOfPattern = UnicodeString(character);
567         int32_t length = curPartOfPattern.length();
568         if ((option == "long" && length != LONG_ERA_LENGTH) || (option == "auto" &&
569             defaultStyle ==  DefaultStyle::LONG)) {
570             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(longChar)));
571         } else if ((option == "short" && length != SHORT_ERA_LENGTH) || (option == "auto" &&
572             (defaultStyle ==  DefaultStyle::DEFAULT || defaultStyle ==  DefaultStyle::SHORT))) {
573             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(shortChar)));
574         } else if (option == "narrow" && length != NARROW_LENGTH) {
575             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(narrowChar)));
576         }
577     }
578 }
579 
ComputeEraOfPattern(std::string option,char16_t character,std::string longChar,std::string shortChar,std::string narrowChar)580 void DateTimeFormat::ComputeEraOfPattern(std::string option, char16_t character, std::string longChar,
581     std::string shortChar, std::string narrowChar)
582 {
583     if (!option.empty()) {
584         UnicodeString curPartOfPattern = UnicodeString(character);
585         int32_t length = curPartOfPattern.length();
586         if ((option == "long" && length != LONG_ERA_LENGTH) || (option == "auto" &&
587             defaultStyle ==  DefaultStyle::LONG)) {
588             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(longChar)));
589         } else if ((option == "short" && length != SHORT_ERA_LENGTH) || (option == "auto" &&
590             defaultStyle ==  DefaultStyle::DEFAULT)) {
591             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(shortChar)));
592         } else if ((option == "narrow" && length != NARROW_LENGTH) || (option == "auto" &&
593             defaultStyle ==  DefaultStyle::SHORT)) {
594             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(narrowChar)));
595         }
596     }
597 }
598 
Format(int64_t milliseconds)599 std::string DateTimeFormat::Format(int64_t milliseconds)
600 {
601     if (!createSuccess || calendar == nullptr || dateFormat == nullptr) {
602         return PseudoLocalizationProcessor("");
603     }
604     UErrorCode status = U_ZERO_ERROR;
605     std::string result;
606     UnicodeString dateString;
607     calendar->clear();
608     std::string timezoneStr = timeZone.empty() ? LocaleConfig::GetSystemTimezone() : timeZone;
609     auto zone = std::unique_ptr<TimeZone>(TimeZone::createTimeZone(timezoneStr.c_str()));
610     if (zone != nullptr) {
611         calendar->setTimeZone(*zone);
612         dateFormat->setTimeZone(*zone);
613     }
614     calendar->setTime((UDate)milliseconds, status);
615     dateFormat->format(calendar->getTime(status), dateString, status);
616     dateString.toUTF8String(result);
617     return PseudoLocalizationProcessor(result);
618 }
619 
FormatRange(int64_t fromMilliseconds,int64_t toMilliseconds)620 std::string DateTimeFormat::FormatRange(int64_t fromMilliseconds, int64_t toMilliseconds)
621 {
622     if (!createSuccess || calendar == nullptr || dateIntvFormat == nullptr) {
623         return PseudoLocalizationProcessor("");
624     }
625     UErrorCode status = U_ZERO_ERROR;
626     std::string result;
627     UnicodeString dateString;
628     calendar->clear();
629     std::string timezoneStr = timeZone.empty() ? LocaleConfig::GetSystemTimezone() : timeZone;
630     auto zone = std::unique_ptr<TimeZone>(TimeZone::createTimeZone(timezoneStr.c_str()));
631     if (zone != nullptr) {
632         calendar->setTimeZone(*zone);
633         dateIntvFormat->setTimeZone(*zone);
634     }
635     calendar->setTime((UDate)fromMilliseconds, status);
636     if (U_FAILURE(status)) {
637         return PseudoLocalizationProcessor("");
638     }
639     auto toCalendar = std::unique_ptr<Calendar>(Calendar::createInstance(locale, status));
640     if (U_FAILURE(status) || toCalendar == nullptr) {
641         return PseudoLocalizationProcessor("");
642     }
643     toCalendar->clear();
644     if (zone != nullptr) {
645         toCalendar->setTimeZone(*zone);
646     }
647     toCalendar->setTime((UDate)toMilliseconds, status);
648     if (U_FAILURE(status)) {
649         return PseudoLocalizationProcessor("");
650     }
651     FieldPosition pos = 0;
652     dateIntvFormat->format(*calendar, *toCalendar, dateString, pos, status);
653     if (U_FAILURE(status)) {
654         return PseudoLocalizationProcessor("");
655     }
656     dateString.toUTF8String(result);
657     return PseudoLocalizationProcessor(result);
658 }
659 
GetResolvedOptions(std::map<std::string,std::string> & map)660 void DateTimeFormat::GetResolvedOptions(std::map<std::string, std::string> &map)
661 {
662     if (!createSuccess || localeInfo == nullptr || dateFormat == nullptr) {
663         return;
664     }
665     map.insert(std::make_pair("locale", localeTag));
666     if (!(localeInfo->GetCalendar()).empty()) {
667         map.insert(std::make_pair("calendar", localeInfo->GetCalendar()));
668     } else {
669         map.insert(std::make_pair("calendar", calendar->getType()));
670     }
671     if (!dateStyle.empty()) {
672         map.insert(std::make_pair("dateStyle", dateStyle));
673     }
674     if (!timeStyle.empty()) {
675         map.insert(std::make_pair("timeStyle", timeStyle));
676     }
677     if (!hourCycle.empty()) {
678         map.insert(std::make_pair("hourCycle", hourCycle));
679     } else if (!(localeInfo->GetHourCycle()).empty()) {
680         map.insert(std::make_pair("hourCycle", localeInfo->GetHourCycle()));
681     }
682     if (!timeZone.empty()) {
683         map.insert(std::make_pair("timeZone", timeZone));
684     } else {
685         UnicodeString timeZoneID("");
686         std::string timeZoneString;
687         dateFormat->getTimeZone().getID(timeZoneID).toUTF8String(timeZoneString);
688         map.insert(std::make_pair("timeZone", timeZoneString));
689     }
690     if (!timeZoneName.empty()) {
691         map.insert(std::make_pair("timeZoneName", timeZoneName));
692     }
693     if (!numberingSystem.empty()) {
694         map.insert(std::make_pair("numberingSystem", numberingSystem));
695     } else if (!(localeInfo->GetNumberingSystem()).empty()) {
696         map.insert(std::make_pair("numberingSystem", localeInfo->GetNumberingSystem()));
697     } else {
698         UErrorCode status = U_ZERO_ERROR;
699         auto numSys = std::unique_ptr<NumberingSystem>(NumberingSystem::createInstance(locale, status));
700         if (U_SUCCESS(status)) {
701             map.insert(std::make_pair("numberingSystem", numSys->getName()));
702         }
703     }
704     GetAdditionalResolvedOptions(map);
705 }
706 
GetAdditionalResolvedOptions(std::map<std::string,std::string> & map)707 void DateTimeFormat::GetAdditionalResolvedOptions(std::map<std::string, std::string> &map)
708 {
709     if (!hour12.empty()) {
710         map.insert(std::make_pair("hour12", hour12));
711     }
712     if (!weekday.empty()) {
713         map.insert(std::make_pair("weekday", weekday));
714     }
715     if (!era.empty()) {
716         map.insert(std::make_pair("era", era));
717     }
718     if (!year.empty()) {
719         map.insert(std::make_pair("year", year));
720     }
721     if (!month.empty()) {
722         map.insert(std::make_pair("month", month));
723     }
724     if (!day.empty()) {
725         map.insert(std::make_pair("day", day));
726     }
727     if (!hour.empty()) {
728         map.insert(std::make_pair("hour", hour));
729     }
730     if (!minute.empty()) {
731         map.insert(std::make_pair("minute", minute));
732     }
733     if (!second.empty()) {
734         map.insert(std::make_pair("second", second));
735     }
736     if (!dayPeriod.empty()) {
737         map.insert(std::make_pair("dayPeriod", dayPeriod));
738     }
739     if (!localeMatcher.empty()) {
740         map.insert(std::make_pair("localeMatcher", localeMatcher));
741     }
742     if (!formatMatcher.empty()) {
743         map.insert(std::make_pair("formatMatcher", formatMatcher));
744     }
745 }
746 
GetDateStyle() const747 std::string DateTimeFormat::GetDateStyle() const
748 {
749     return dateStyle;
750 }
751 
GetTimeStyle() const752 std::string DateTimeFormat::GetTimeStyle() const
753 {
754     return timeStyle;
755 }
756 
GetHourCycle() const757 std::string DateTimeFormat::GetHourCycle() const
758 {
759     return hourCycle;
760 }
761 
GetTimeZone() const762 std::string DateTimeFormat::GetTimeZone() const
763 {
764     return timeZone;
765 }
766 
GetTimeZoneName() const767 std::string DateTimeFormat::GetTimeZoneName() const
768 {
769     return timeZoneName;
770 }
771 
GetNumberingSystem() const772 std::string DateTimeFormat::GetNumberingSystem() const
773 {
774     return numberingSystem;
775 }
776 
GetHour12() const777 std::string DateTimeFormat::GetHour12() const
778 {
779     return hour12;
780 }
781 
GetWeekday() const782 std::string DateTimeFormat::GetWeekday() const
783 {
784     return weekday;
785 }
786 
GetEra() const787 std::string DateTimeFormat::GetEra() const
788 {
789     return era;
790 }
791 
GetYear() const792 std::string DateTimeFormat::GetYear() const
793 {
794     return year;
795 }
796 
GetMonth() const797 std::string DateTimeFormat::GetMonth() const
798 {
799     return month;
800 }
801 
GetDay() const802 std::string DateTimeFormat::GetDay() const
803 {
804     return day;
805 }
806 
GetHour() const807 std::string DateTimeFormat::GetHour() const
808 {
809     return hour;
810 }
811 
GetMinute() const812 std::string DateTimeFormat::GetMinute() const
813 {
814     return minute;
815 }
816 
GetSecond() const817 std::string DateTimeFormat::GetSecond() const
818 {
819     return second;
820 }
821 
Init()822 bool DateTimeFormat::Init()
823 {
824     SetHwIcuDirectory();
825     return true;
826 }
827 
GetDefaultStyle()828 DateTimeFormat::DefaultStyle DateTimeFormat::GetDefaultStyle()
829 {
830     char value[LocaleConfig::CONFIG_LEN];
831     int code = GetParameter(DEVICE_TYPE_NAME, "", value, LocaleConfig::CONFIG_LEN);
832     if (code > 0) {
833         std::string deviceType = value;
834         if (DeviceToStyle.find(deviceType) != DeviceToStyle.end()) {
835             return DeviceToStyle[deviceType];
836         }
837     }
838     return DefaultStyle::DEFAULT;
839 }
840 
InitPatternByDateStyle()841 bool DateTimeFormat::InitPatternByDateStyle()
842 {
843     icu::UnicodeString tempPattern = GetBestPattern(DateFormat::EStyle::kShort, DateFormat::EStyle::kNone, locale);
844     std::string number = LocaleConfig::GetPatternNumberFromLocale(finalLocale);
845     auto iter = EXT_PARAM_TO_PATTERNS.find(number);
846     icu::UnicodeString replacePattern;
847     if (iter != EXT_PARAM_TO_PATTERNS.end()) {
848         replacePattern = iter->second[YMD_INDEX];
849         icu::UnicodeString dayPattern = GetDayPatternFromLocale(finalLocale);
850         replacePattern.findAndReplace(D_SKELETON, dayPattern);
851         ReplacePattern(tempPattern, replacePattern);
852     }
853     return InitFormatter();
854 }
855 
InitPatternByNumeric()856 bool DateTimeFormat::InitPatternByNumeric()
857 {
858     icu::UnicodeString tempSkeleton;
859     size_t index = -1;
860     if (year == NUMERIC_STR && month == NUMERIC_STR && day == NUMERIC_STR) {
861         tempSkeleton = YMD_SKELETON;
862         index = YMD_INDEX;
863     } else if (year == NUMERIC_STR && month == NUMERIC_STR && day.empty()) {
864         tempSkeleton = YM_SKELETON;
865         index = YM_INDEX;
866     } else if (year.empty() && month == NUMERIC_STR && day == NUMERIC_STR) {
867         tempSkeleton = MD_SKELETON;
868         index = MD_INDEX;
869     }
870     if (tempSkeleton.isEmpty()) {
871         return false;
872     }
873     std::string number = LocaleConfig::GetPatternNumberFromLocale(finalLocale);
874     auto iter = EXT_PARAM_TO_PATTERNS.find(number);
875     icu::UnicodeString replacePattern;
876     icu::UnicodeString tempPattern = GetBestPattern(tempSkeleton, locale);
877     if (iter != EXT_PARAM_TO_PATTERNS.end()) {
878         replacePattern = iter->second[index];
879         icu::UnicodeString dayPattern = GetDayPatternFromLocale(finalLocale);
880         replacePattern.findAndReplace(D_SKELETON, dayPattern);
881         ReplacePattern(tempPattern, replacePattern);
882     }
883     return InitFormatter();
884 }
885 
ReplacePattern(const icu::UnicodeString & tempPattern,const icu::UnicodeString & replacePattern)886 void DateTimeFormat::ReplacePattern(const icu::UnicodeString& tempPattern, const icu::UnicodeString& replacePattern)
887 {
888     if (tempPattern.isEmpty()) {
889         HILOG_ERROR_I18N("DateTimeFormat::ReplacePattern: tempPattern is empty.");
890         return;
891     }
892     int32_t startIndex = pattern.indexOf(tempPattern);
893     if (startIndex == -1) {
894         HILOG_ERROR_I18N("DateTimeFormat::ReplacePattern: startIndex is -1.");
895         return;
896     }
897     int32_t length = tempPattern.length();
898     pattern.replace(startIndex, length, replacePattern);
899 }
900 
GetPatternsFromLocale(const std::string & localeTag)901 std::unordered_map<std::string, std::string> DateTimeFormat::GetPatternsFromLocale(const std::string& localeTag)
902 {
903     std::unordered_map<std::string, std::string> result;
904     for (const auto& item : EXT_PARAM_TO_PATTERNS) {
905         icu::UnicodeString pattern = item.second[YMD_INDEX];
906         std::string tempPattern;
907         pattern.toUTF8String(tempPattern);
908         result.insert(std::make_pair(tempPattern, item.first));
909     }
910 
911     icu::UnicodeString pattern = GetSingleDayPatternFromLocale(localeTag);
912     icu::UnicodeString patternWithoutSymbol = pattern;
913     patternWithoutSymbol.findAndReplace(LTR_SYMBOL, "");
914     if (patternWithoutSymbol.indexOf(RTL_SYMBOL) != -1) {
915         patternWithoutSymbol.findAndReplace(RTL_SYMBOL, "");
916         patternWithoutSymbol.reverse();
917     }
918     std::string tempPatternWithoutSymbol;
919     patternWithoutSymbol.toUTF8String(tempPatternWithoutSymbol);
920     auto iter = result.find(tempPatternWithoutSymbol);
921     if (iter != result.end()) {
922         result.erase(iter);
923     }
924 
925     std::string tempPattern;
926     pattern.toUTF8String(tempPattern);
927     result.insert(std::make_pair(tempPattern, ""));
928     return result;
929 }
930 
GetPatternFromLocale(const std::string & localeTag)931 icu::UnicodeString DateTimeFormat::GetPatternFromLocale(const std::string& localeTag)
932 {
933     UErrorCode status = U_ZERO_ERROR;
934     icu::Locale locale = icu::Locale::forLanguageTag(StringPiece(localeTag), status);
935     if (U_FAILURE(status)) {
936         HILOG_ERROR_I18N("DateTimeFormat::GetPatternFromLocale: Create icu locale failed.");
937         return "";
938     }
939 
940     icu::DateFormat* icuDateFormet = icu::DateFormat::createDateInstance(icu::DateFormat::SHORT, locale);
941     if (icuDateFormet == nullptr) {
942         HILOG_ERROR_I18N("DateTimeFormat::GetPatternFromLocale: Create icuDateFormet failed.");
943         return "";
944     }
945     icu::SimpleDateFormat* icuSimpleDateFormat = reinterpret_cast<icu::SimpleDateFormat *>(icuDateFormet);
946     icu::UnicodeString result;
947     icuSimpleDateFormat->toPattern(result);
948     delete icuSimpleDateFormat;
949     return result;
950 }
951 
GetYMDPatternFromNumber(const std::string & number)952 icu::UnicodeString DateTimeFormat::GetYMDPatternFromNumber(const std::string& number)
953 {
954     auto iter = EXT_PARAM_TO_PATTERNS.find(number);
955     if (iter == EXT_PARAM_TO_PATTERNS.end()) {
956         HILOG_ERROR_I18N("DateTimeFormat::GetYMDPatternFromNumber: Invalid number %{public}s.", number.c_str());
957         return "";
958     }
959     std::vector<icu::UnicodeString> patterns = iter->second;
960     return patterns[YMD_INDEX];
961 }
962 
GetDateSampleFromPattern(const icu::UnicodeString & pattern,const std::string & localeTag)963 std::string DateTimeFormat::GetDateSampleFromPattern(const icu::UnicodeString& pattern, const std::string& localeTag)
964 {
965     std::string localeWithoutCustExtParam = LocaleConfig::RemoveCustExtParam(localeTag);
966     UErrorCode status = U_ZERO_ERROR;
967     icu::Locale icuLocale = icu::Locale::forLanguageTag(StringPiece(localeWithoutCustExtParam), status);
968     if (U_FAILURE(status)) {
969         HILOG_ERROR_I18N("DateTimeFormat::GetDateSampleFromPattern: Create icu locale failed.");
970         return "";
971     }
972     std::unique_ptr<icu::SimpleDateFormat> simpleDateFormat =
973         std::make_unique<icu::SimpleDateFormat>(pattern, icuLocale, status);
974     if (U_FAILURE(status)) {
975         HILOG_ERROR_I18N("DateTimeFormat::GetDateSampleFromPattern: Create simpleDateFormat failed.");
976         return "";
977     }
978     icu::UnicodeString formatResult;
979     simpleDateFormat->format(DEFAULT_TIME, formatResult, status);
980     if (U_FAILURE(status)) {
981         HILOG_ERROR_I18N("DateTimeFormat::GetDateSampleFromPattern: Format failed.");
982         return "";
983     }
984     std::string result;
985     formatResult.toUTF8String(result);
986     return result;
987 }
988 
IsValidPatternNumber(const std::string & number)989 bool DateTimeFormat::IsValidPatternNumber(const std::string& number)
990 {
991     if (EXT_PARAM_TO_PATTERNS.find(number) == EXT_PARAM_TO_PATTERNS.end()) {
992         return false;
993     }
994     return true;
995 }
996 
GetBestPattern(const icu::UnicodeString & skeleton,const icu::Locale & icuLocale)997 icu::UnicodeString DateTimeFormat::GetBestPattern(const icu::UnicodeString& skeleton, const icu::Locale& icuLocale)
998 {
999     UErrorCode status = U_ZERO_ERROR;
1000     auto patternGenerator =
1001         std::unique_ptr<DateTimePatternGenerator>(DateTimePatternGenerator::createInstance(icuLocale, status));
1002     if (U_FAILURE(status) || patternGenerator == nullptr) {
1003         HILOG_ERROR_I18N("DateTimeFormat::GetBestPattern: Create DateTimePatternGenerator instance failed.");
1004         return "";
1005     }
1006     icu::UnicodeString tempPattern = patternGenerator->getBestPattern(skeleton, status);
1007     if (U_FAILURE(status)) {
1008         HILOG_ERROR_I18N("DateTimeFormat::GetBestPattern: Get best pattern from skeleton failed.");
1009         return "";
1010     }
1011     tempPattern = patternGenerator->replaceFieldTypes(tempPattern, skeleton, status);
1012     if (U_FAILURE(status)) {
1013         HILOG_ERROR_I18N("DateTimeFormat::ReplacePatternByNumeric: Replace field types failed.");
1014         return "";
1015     }
1016     tempPattern = patternGenerator->getBestPattern(tempPattern, status);
1017     if (U_FAILURE(status)) {
1018         HILOG_ERROR_I18N("DateTimeFormat::ReplacePatternByNumeric: Get best pattern from tempPattern failed.");
1019         return "";
1020     }
1021     return tempPattern;
1022 }
1023 
GetBestPattern(icu::DateFormat::EStyle dateStyle,icu::DateFormat::EStyle timeStyle,const icu::Locale & icuLocale)1024 icu::UnicodeString DateTimeFormat::GetBestPattern(icu::DateFormat::EStyle dateStyle, icu::DateFormat::EStyle timeStyle,
1025     const icu::Locale& icuLocale)
1026 {
1027     icu::DateFormat* tempDateFormat = DateFormat::createDateTimeInstance(dateStyle, timeStyle, icuLocale);
1028     if (tempDateFormat == nullptr) {
1029         HILOG_ERROR_I18N("DateTimeFormat::GetBestPattern: Create DateFormat instance failed.");
1030         return "";
1031     }
1032     SimpleDateFormat* simpleDateFormat = static_cast<SimpleDateFormat*>(tempDateFormat);
1033     std::unique_ptr<SimpleDateFormat> simDateFormatPtr = std::unique_ptr<SimpleDateFormat>(simpleDateFormat);
1034     if (simDateFormatPtr == nullptr) {
1035         HILOG_ERROR_I18N("DateTimeFormat::GetBestPattern: Create simpleDateFormat failed.");
1036         return "";
1037     }
1038     icu::UnicodeString pattern;
1039     simDateFormatPtr->toPattern(pattern);
1040     return pattern;
1041 }
1042 
InitFormatter()1043 bool DateTimeFormat::InitFormatter()
1044 {
1045     UErrorCode status = U_ZERO_ERROR;
1046     dateFormat = std::make_unique<SimpleDateFormat>(pattern, locale, status);
1047     if (U_FAILURE(status)) {
1048         HILOG_ERROR_I18N("DateTimeFormat::InitFormatter: Create SimpleDateFormat failed.");
1049         return false;
1050     }
1051 
1052     dateIntvFormat =
1053         std::unique_ptr<DateIntervalFormat>(DateIntervalFormat::createInstance(pattern, locale, status));
1054     if (U_FAILURE(status)) {
1055         HILOG_ERROR_I18N("DateTimeFormat::InitFormatter: Create DateIntervalFormat failed.");
1056         return false;
1057     }
1058     return true;
1059 }
1060 
GetDayPatternFromLocale(const std::string & localeTag)1061 icu::UnicodeString DateTimeFormat::GetDayPatternFromLocale(const std::string& localeTag)
1062 {
1063     icu::UnicodeString pattern = DateTimeFormat::GetPatternFromLocale(localeTag);
1064     int32_t index = pattern.indexOf(DD_SKELETON);
1065     if (index == -1) {
1066         return D_SKELETON;
1067     }
1068     return DD_SKELETON;
1069 }
1070 
GetSingleDayPatternFromLocale(const std::string & localeTag)1071 icu::UnicodeString DateTimeFormat::GetSingleDayPatternFromLocale(const std::string& localeTag)
1072 {
1073     icu::UnicodeString pattern = GetPatternFromLocale(localeTag);
1074     pattern.findAndReplace(DD_SKELETON, D_SKELETON);
1075     return pattern;
1076 }
1077 } // namespace I18n
1078 } // namespace Global
1079 } // namespace OHOS
1080