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