• 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 "locale_config.h"
17 #include "ohos/init_data.h"
18 #include "parameter.h"
19 #include "utils.h"
20 
21 namespace OHOS {
22 namespace Global {
23 namespace I18n {
24 const char* DateTimeFormat::DEVICE_TYPE_NAME = "const.product.devicetype";
25 
26 using namespace icu;
27 bool DateTimeFormat::icuInitialized = DateTimeFormat::Init();
28 
29 std::map<std::string, DateFormat::EStyle> DateTimeFormat::dateTimeStyle = {
30     { "full", DateFormat::EStyle::kFull },
31     { "long", DateFormat::EStyle::kLong },
32     { "medium", DateFormat::EStyle::kMedium },
33     { "short", DateFormat::EStyle::kShort }
34 };
35 
36 std::unordered_map<std::string, DateTimeFormat::DefaultStyle> DateTimeFormat::DeviceToStyle = {
37     { "tablet", DefaultStyle::LONG },
38     { "2in1", DefaultStyle::LONG },
39     { "tv", DefaultStyle::LONG },
40     { "pc", DefaultStyle::LONG },
41     { "liteWearable", DefaultStyle::SHORT },
42     { "wearable", DefaultStyle::SHORT },
43     { "watch", DefaultStyle::SHORT }
44 };
45 
46 std::unordered_map<DateTimeFormat::DefaultStyle, DateFormat::EStyle> DateTimeFormat::DefaultDTStyle = {
47     { DefaultStyle::LONG, DateFormat::EStyle::kMedium },
48     { DefaultStyle::DEFAULT, DateFormat::EStyle::kShort },
49     { DefaultStyle::SHORT, DateFormat::EStyle::kShort },
50 };
51 
DateTimeFormat(const std::vector<std::string> & localeTags,std::map<std::string,std::string> & configs)52 DateTimeFormat::DateTimeFormat(const std::vector<std::string> &localeTags, std::map<std::string, std::string> &configs)
53 {
54     defaultStyle = GetDefaultStyle();
55     UErrorCode status = U_ZERO_ERROR;
56     ParseConfigsPartOne(configs);
57     ParseConfigsPartTwo(configs);
58     for (size_t i = 0; i < localeTags.size(); i++) {
59         std::string curLocale = localeTags[i];
60         locale = Locale::forLanguageTag(StringPiece(curLocale), status);
61         if (U_FAILURE(status)) {
62             status = U_ZERO_ERROR;
63             continue;
64         }
65         if (LocaleInfo::allValidLocales.count(locale.getLanguage()) > 0) {
66             createSuccess = InitWithLocale(curLocale, configs);
67             if (!createSuccess || !dateFormat) {
68                 FreeDateTimeFormat();
69                 continue;
70             }
71             break;
72         }
73     }
74     if (!localeInfo || !dateFormat) {
75         createSuccess = InitWithDefaultLocale(configs);
76     }
77 }
78 
FreeDateTimeFormat()79 void DateTimeFormat::FreeDateTimeFormat()
80 {
81     if (calendar != nullptr) {
82         delete calendar;
83         calendar = nullptr;
84     }
85     if (dateFormat != nullptr) {
86         delete dateFormat;
87         dateFormat = nullptr;
88     }
89     if (localeInfo != nullptr) {
90         delete localeInfo;
91         localeInfo = nullptr;
92     }
93 }
94 
~DateTimeFormat()95 DateTimeFormat::~DateTimeFormat()
96 {
97     FreeDateTimeFormat();
98 }
99 
CheckInitSuccess()100 bool DateTimeFormat::CheckInitSuccess()
101 {
102     return (dateIntvFormat == nullptr || calendar == nullptr || dateFormat == nullptr || localeInfo == nullptr) ?
103         false : true;
104 }
105 
CreateInstance(const std::vector<std::string> & localeTags,std::map<std::string,std::string> & configs)106 std::unique_ptr<DateTimeFormat> DateTimeFormat::CreateInstance(const std::vector<std::string> &localeTags,
107                                                                std::map<std::string, std::string> &configs)
108 {
109     std::unique_ptr<DateTimeFormat> dateTimeFormat = std::make_unique<DateTimeFormat>(localeTags, configs);
110     if (!dateTimeFormat->CheckInitSuccess()) {
111         return nullptr;
112     }
113     return dateTimeFormat;
114 }
115 
InitWithLocale(const std::string & curLocale,std::map<std::string,std::string> & configs)116 bool DateTimeFormat::InitWithLocale(const std::string &curLocale, std::map<std::string, std::string> &configs)
117 {
118     localeInfo = new LocaleInfo(curLocale, configs);
119     if (localeInfo == nullptr || !localeInfo->InitSuccess()) {
120         return false;
121     }
122     locale = localeInfo->GetLocale();
123     localeTag = localeInfo->GetBaseName();
124     if (hourCycle.empty()) {
125         hourCycle = localeInfo->GetHourCycle();
126     }
127     if (hour12.empty() && hourCycle.empty() && !LocaleConfig::IsEmpty24HourClock()) {
128         bool is24HourClock = LocaleConfig::Is24HourClock();
129         hour12 = is24HourClock ? "false" : "true";
130     }
131     ComputeHourCycleChars();
132     ComputeSkeleton();
133     UErrorCode status = U_ZERO_ERROR;
134     if (!configs.size()) {
135         InitDateFormatWithoutConfigs(status);
136     } else {
137         InitDateFormat(status);
138     }
139     if (!U_SUCCESS(status)) {
140         return false;
141     }
142     status = U_ZERO_ERROR;
143     calendar = Calendar::createInstance(locale, status);
144     if (!U_SUCCESS(status)) {
145         return false;
146     }
147     return true;
148 }
149 
InitWithDefaultLocale(std::map<std::string,std::string> & configs)150 bool DateTimeFormat::InitWithDefaultLocale(std::map<std::string, std::string> &configs)
151 {
152     if (localeInfo != nullptr) {
153         delete localeInfo;
154         localeInfo = nullptr;
155     }
156     if (dateFormat != nullptr) {
157         delete dateFormat;
158         dateFormat = nullptr;
159     }
160     return InitWithLocale(LocaleConfig::GetSystemLocale(), configs);
161 }
162 
InitDateFormatWithoutConfigs(UErrorCode & status)163 void DateTimeFormat::InitDateFormatWithoutConfigs(UErrorCode &status)
164 {
165     dateFormat = DateFormat::createDateInstance(DefaultDTStyle[defaultStyle], locale);
166     SimpleDateFormat *simDateFormat = static_cast<SimpleDateFormat*>(dateFormat);
167     if (simDateFormat != nullptr) {
168         simDateFormat->toPattern(pattern);
169     }
170     dateIntvFormat =
171         std::unique_ptr<DateIntervalFormat>(DateIntervalFormat::createInstance(pattern, locale, status));
172 }
173 
FixPatternPartOne()174 void DateTimeFormat::FixPatternPartOne()
175 {
176     if (hour12 == "true") {
177         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("H")),
178             icu::UnicodeString::fromUTF8(StringPiece("h")));
179         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
180             icu::UnicodeString::fromUTF8(StringPiece("h")));
181         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
182             icu::UnicodeString::fromUTF8(StringPiece("h")));
183     } else if (hour12 == "false") {
184         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("h")),
185             icu::UnicodeString::fromUTF8(StringPiece("H")));
186         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
187             icu::UnicodeString::fromUTF8(StringPiece("H")));
188         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
189             icu::UnicodeString::fromUTF8(StringPiece("H")));
190         RemoveAmPmChar();
191     } else if (hourCycle != "") {
192         FixPatternPartTwo();
193     }
194 }
195 
FixPatternPartTwo()196 void DateTimeFormat::FixPatternPartTwo()
197 {
198     if (hourCycle == "h11") {
199         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("h")),
200             icu::UnicodeString::fromUTF8(StringPiece("k")));
201         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("H")),
202             icu::UnicodeString::fromUTF8(StringPiece("k")));
203         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
204             icu::UnicodeString::fromUTF8(StringPiece("k")));
205     } else if (hourCycle == "h12") {
206         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("H")),
207             icu::UnicodeString::fromUTF8(StringPiece("h")));
208         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
209             icu::UnicodeString::fromUTF8(StringPiece("h")));
210         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
211             icu::UnicodeString::fromUTF8(StringPiece("h")));
212     } else if (hourCycle == "h23") {
213         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("h")),
214             icu::UnicodeString::fromUTF8(StringPiece("K")));
215         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("H")),
216             icu::UnicodeString::fromUTF8(StringPiece("K")));
217         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
218             icu::UnicodeString::fromUTF8(StringPiece("K")));
219         RemoveAmPmChar();
220     } else if (hourCycle == "h24") {
221         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("h")),
222             icu::UnicodeString::fromUTF8(StringPiece("H")));
223         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("k")),
224             icu::UnicodeString::fromUTF8(StringPiece("H")));
225         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("K")),
226             icu::UnicodeString::fromUTF8(StringPiece("H")));
227         RemoveAmPmChar();
228     }
229 }
230 
RemoveAmPmChar()231 void DateTimeFormat::RemoveAmPmChar()
232 {
233     std::string patternString = "";
234     pattern.toUTF8String(patternString);
235     size_t amPmCharStartIdx = 0;
236     size_t amPmCharEndIdx = 0;
237     for (size_t i = 0; i < patternString.length(); i++) {
238         if (patternString[i] != 'a') {
239             continue;
240         }
241         if ((i + 1) < patternString.length() && patternString[i + 1] == 't') {
242             continue;
243         }
244         if (!i) {
245             amPmCharStartIdx = i;
246         } else {
247             amPmCharStartIdx = i - 1;
248             while (amPmCharStartIdx > 0 && patternString[amPmCharStartIdx] == ' ') {
249                 amPmCharStartIdx -= 1;
250             }
251             if (amPmCharStartIdx || patternString[amPmCharStartIdx] != ' ') {
252                 amPmCharStartIdx += 1;
253             }
254         }
255         amPmCharEndIdx = i + 1;
256         while (amPmCharEndIdx < patternString.length() && patternString[amPmCharEndIdx] == ' ') {
257             amPmCharEndIdx += 1;
258         }
259         break;
260     }
261     size_t length = amPmCharEndIdx - amPmCharStartIdx;
262     if (length) {
263         if (!amPmCharStartIdx || amPmCharEndIdx == patternString.length()) {
264             patternString = patternString.replace(amPmCharStartIdx, length, "");
265         } else {
266             patternString = patternString.replace(amPmCharStartIdx, length, " ");
267         }
268         pattern = icu::UnicodeString(patternString.data(), patternString.length());
269     }
270 }
271 
InitDateFormat(UErrorCode & status)272 void DateTimeFormat::InitDateFormat(UErrorCode &status)
273 {
274     if (!dateStyle.empty() || !timeStyle.empty()) {
275         DateFormat::EStyle dateStyleValue = DateFormat::EStyle::kNone;
276         DateFormat::EStyle timeStyleValue = DateFormat::EStyle::kNone;
277         if (!dateStyle.empty()) {
278             if (dateTimeStyle.count(dateStyle) > 0) {
279                 dateStyleValue = dateTimeStyle[dateStyle];
280             } else if (dateStyle == "auto") {
281                 dateStyleValue = DefaultDTStyle[defaultStyle];
282             }
283         }
284         if (!timeStyle.empty()) {
285             if (dateTimeStyle.count(timeStyle) > 0) {
286                 timeStyleValue = dateTimeStyle[timeStyle];
287             } else if (timeStyle == "auto") {
288                 timeStyleValue = DefaultDTStyle[defaultStyle];
289             }
290         }
291         dateFormat = DateFormat::createDateTimeInstance(dateStyleValue, timeStyleValue, locale);
292         SimpleDateFormat *simDateFormat = static_cast<SimpleDateFormat*>(dateFormat);
293         if (simDateFormat != nullptr) {
294             simDateFormat->toPattern(pattern);
295         }
296         FixPatternPartOne();
297         delete dateFormat;
298         dateFormat = new SimpleDateFormat(pattern, locale, status);
299         if (!U_SUCCESS(status)) {
300             return;
301         }
302     } else {
303         auto patternGenerator =
304             std::unique_ptr<DateTimePatternGenerator>(DateTimePatternGenerator::createInstance(locale, status));
305         if (!U_SUCCESS(status)) {
306             return;
307         }
308         ComputePattern();
309         pattern =
310             patternGenerator->replaceFieldTypes(patternGenerator->getBestPattern(pattern, status), pattern, status);
311         pattern = patternGenerator->getBestPattern(pattern, status);
312         SetDayPeriod();
313         status = U_ZERO_ERROR;
314         dateFormat = new SimpleDateFormat(pattern, locale, status);
315         if (!U_SUCCESS(status)) {
316             return;
317         }
318     }
319     status = U_ZERO_ERROR;
320     dateIntvFormat =
321         std::unique_ptr<DateIntervalFormat>(DateIntervalFormat::createInstance(pattern, locale, status));
322 }
323 
SetDayPeriod()324 void DateTimeFormat::SetDayPeriod()
325 {
326     if (dayPeriod == "short" || (dayPeriod == "auto" && defaultStyle ==  DefaultStyle::DEFAULT)) {
327         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("a")),
328             icu::UnicodeString::fromUTF8(StringPiece("B")));
329     } else if (dayPeriod == "long" || (dayPeriod == "auto" && defaultStyle ==  DefaultStyle::LONG)) {
330         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("a")),
331             icu::UnicodeString::fromUTF8(StringPiece("BBBB")));
332     } else if (dayPeriod == "narrow" || (dayPeriod == "auto" && defaultStyle ==  DefaultStyle::SHORT)) {
333         pattern.findAndReplace(icu::UnicodeString::fromUTF8(StringPiece("a")),
334             icu::UnicodeString::fromUTF8(StringPiece("BBBBB")));
335     }
336 }
337 
ParseConfigsPartOne(std::map<std::string,std::string> & configs)338 void DateTimeFormat::ParseConfigsPartOne(std::map<std::string, std::string> &configs)
339 {
340     if (configs.count("dateStyle") > 0) {
341         dateStyle = configs["dateStyle"];
342     }
343     if (configs.count("timeStyle") > 0) {
344         timeStyle = configs["timeStyle"];
345     }
346     if (configs.count("year") > 0) {
347         year = configs["year"];
348     }
349     if (configs.count("month") > 0) {
350         month = configs["month"];
351     }
352     if (configs.count("day") > 0) {
353         day = configs["day"];
354     }
355     if (configs.count("hour") > 0) {
356         hour = configs["hour"];
357     }
358     if (configs.count("minute") > 0) {
359         minute = configs["minute"];
360     }
361     if (configs.count("second") > 0) {
362         second = configs["second"];
363     }
364 }
365 
ParseConfigsPartTwo(std::map<std::string,std::string> & configs)366 void DateTimeFormat::ParseConfigsPartTwo(std::map<std::string, std::string> &configs)
367 {
368     if (configs.count("hourCycle") > 0) {
369         hourCycle = configs["hourCycle"];
370     }
371     if (configs.count("timeZone") > 0) {
372         timeZone = configs["timeZone"];
373     }
374     if (configs.count("numberingSystem") > 0) {
375         numberingSystem = configs["numberingSystem"];
376     }
377     if (configs.count("hour12") > 0) {
378         hour12 = configs["hour12"];
379     }
380     if (configs.count("weekday") > 0) {
381         weekday = configs["weekday"];
382     }
383     if (configs.count("era") > 0) {
384         era = configs["era"];
385     }
386     if (configs.count("timeZoneName") > 0) {
387         timeZoneName = configs["timeZoneName"];
388     }
389     if (configs.count("dayPeriod") > 0) {
390         dayPeriod = configs["dayPeriod"];
391     }
392     if (configs.count("localeMatcher") > 0) {
393         localeMatcher = configs["localeMatcher"];
394     }
395     if (configs.count("formatMatcher") > 0) {
396         formatMatcher = configs["formatMatcher"];
397     }
398 }
399 
ComputeSkeleton()400 void DateTimeFormat::ComputeSkeleton()
401 {
402     if (year.empty() && month.empty() && day.empty() && hour.empty() && minute.empty() && second.empty() &&
403         weekday.empty()) {
404         pattern.append("yMd");
405     }
406     AddOptions(year, yearChar);
407     AddOptions(month, monthChar);
408     AddOptions(day, dayChar);
409     AddOptions(hour, hourChar);
410     AddOptions(minute, minuteChar);
411     AddOptions(second, secondChar);
412     if ((hourCycle == "h12" || hourCycle == "h11" || hour12 == "true") && !hour.empty()) {
413         pattern.append(amPmChar);
414     }
415     AddOptions(timeZoneName, timeZoneChar);
416     AddOptions(weekday, weekdayChar);
417     AddOptions(era, eraChar);
418 }
419 
AddOptions(std::string option,char16_t optionChar)420 void DateTimeFormat::AddOptions(std::string option, char16_t optionChar)
421 {
422     if (!option.empty()) {
423         pattern.append(optionChar);
424     }
425 }
426 
ComputeHourCycleChars()427 void DateTimeFormat::ComputeHourCycleChars()
428 {
429     if (!hour12.empty()) {
430         if (hour12 == "true") {
431             hourNumericString = "h";
432             hourTwoDigitString = "hh";
433         } else {
434             hourNumericString = "H";
435             hourTwoDigitString = "HH";
436         }
437     } else {
438         if (hourCycle == "h11") {
439             hourNumericString = "K";
440             hourTwoDigitString = "KK";
441         } else if (hourCycle == "h12") {
442             hourNumericString = "h";
443             hourTwoDigitString = "hh";
444         } else if (hourCycle == "h23") {
445             hourNumericString = "H";
446             hourTwoDigitString = "HH";
447         } else if (hourCycle == "h24") {
448             hourNumericString = "k";
449             hourTwoDigitString = "kk";
450         }
451     }
452 }
453 
ComputePattern()454 void DateTimeFormat::ComputePattern()
455 {
456     ComputePartOfPattern(year, yearChar, "yy", "yyyy");
457     ComputePartOfPattern(day, dayChar, "dd", "d");
458     ComputePartOfPattern(hour, hourChar, hourTwoDigitString, hourNumericString);
459     ComputePartOfPattern(minute, minuteChar, "mm", "mm");
460     ComputePartOfPattern(second, secondChar, "ss", "ss");
461     if (!month.empty()) {
462         UnicodeString monthOfPattern = UnicodeString(monthChar);
463         int32_t length = monthOfPattern.length();
464         if (month == "numeric" && length != NUMERIC_LENGTH) {
465             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("M")));
466         } else if (month == "2-digit" && length != TWO_DIGIT_LENGTH) {
467             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("MM")));
468         } else if ((month == "long" && length != LONG_LENGTH) || (month == "auto" &&
469             defaultStyle ==  DefaultStyle::LONG)) {
470             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("MMMM")));
471         } else if ((month == "short" && length != SHORT_LENGTH) || (month == "auto" &&
472             (defaultStyle ==  DefaultStyle::DEFAULT || defaultStyle ==  DefaultStyle::SHORT))) {
473             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("MMM")));
474         } else if (month == "narrow" && length != NARROW_LENGTH) {
475             pattern.findAndReplace(monthOfPattern, UnicodeString::fromUTF8(StringPiece("MMMMM")));
476         }
477     }
478 
479     ComputeTimeZoneOfPattern(timeZoneName, timeZoneChar, "zzzz", "O");
480     ComputeWeekdayOfPattern(weekday, weekdayChar, "EEEE", "E", "EEEEE");
481     ComputeEraOfPattern(era, eraChar, "GGGG", "G", "GGGGG");
482 }
483 
ComputePartOfPattern(std::string option,char16_t character,std::string twoDigitChar,std::string numericChar)484 void DateTimeFormat::ComputePartOfPattern(std::string option, char16_t character, std::string twoDigitChar,
485     std::string numericChar)
486 {
487     if (!option.empty()) {
488         UnicodeString curPartOfPattern = UnicodeString(character);
489         if (option == "2-digit") {
490             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(twoDigitChar)));
491         } else if (option == "numeric") {
492             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(numericChar)));
493         }
494     }
495 }
496 
ComputeTimeZoneOfPattern(std::string option,char16_t character,std::string longChar,std::string shortChar)497 void DateTimeFormat::ComputeTimeZoneOfPattern(std::string option, char16_t character, std::string longChar,
498     std::string shortChar)
499 {
500     if (!option.empty()) {
501         UnicodeString timeZoneOfPattern = UnicodeString(character);
502         if (option == "long" || (option == "auto" && defaultStyle ==  DefaultStyle::LONG)) {
503             pattern.findAndReplace(timeZoneOfPattern, UnicodeString::fromUTF8(StringPiece(longChar)));
504         } else if (option == "short" || (option == "auto" && (defaultStyle ==  DefaultStyle::DEFAULT ||
505             defaultStyle ==  DefaultStyle::SHORT))) {
506             pattern.findAndReplace(timeZoneOfPattern, UnicodeString::fromUTF8(StringPiece(shortChar)));
507         }
508     }
509 }
510 
ComputeWeekdayOfPattern(std::string option,char16_t character,std::string longChar,std::string shortChar,std::string narrowChar)511 void DateTimeFormat::ComputeWeekdayOfPattern(std::string option, char16_t character, std::string longChar,
512     std::string shortChar, std::string narrowChar)
513 {
514     if (!option.empty()) {
515         UnicodeString curPartOfPattern = UnicodeString(character);
516         int32_t length = curPartOfPattern.length();
517         if ((option == "long" && length != LONG_ERA_LENGTH) || (option == "auto" &&
518             defaultStyle ==  DefaultStyle::LONG)) {
519             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(longChar)));
520         } else if ((option == "short" && length != SHORT_ERA_LENGTH) || (option == "auto" &&
521             (defaultStyle ==  DefaultStyle::DEFAULT || defaultStyle ==  DefaultStyle::SHORT))) {
522             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(shortChar)));
523         } else if (option == "narrow" && length != NARROW_LENGTH) {
524             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(narrowChar)));
525         }
526     }
527 }
528 
ComputeEraOfPattern(std::string option,char16_t character,std::string longChar,std::string shortChar,std::string narrowChar)529 void DateTimeFormat::ComputeEraOfPattern(std::string option, char16_t character, std::string longChar,
530     std::string shortChar, std::string narrowChar)
531 {
532     if (!option.empty()) {
533         UnicodeString curPartOfPattern = UnicodeString(character);
534         int32_t length = curPartOfPattern.length();
535         if ((option == "long" && length != LONG_ERA_LENGTH) || (option == "auto" &&
536             defaultStyle ==  DefaultStyle::LONG)) {
537             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(longChar)));
538         } else if ((option == "short" && length != SHORT_ERA_LENGTH) || (option == "auto" &&
539             defaultStyle ==  DefaultStyle::DEFAULT)) {
540             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(shortChar)));
541         } else if ((option == "narrow" && length != NARROW_LENGTH) || (option == "auto" &&
542             defaultStyle ==  DefaultStyle::SHORT)) {
543             pattern.findAndReplace(curPartOfPattern, UnicodeString::fromUTF8(StringPiece(narrowChar)));
544         }
545     }
546 }
547 
Format(int64_t milliseconds)548 std::string DateTimeFormat::Format(int64_t milliseconds)
549 {
550     if (!createSuccess) {
551         return PseudoLocalizationProcessor("");
552     }
553     UErrorCode status = U_ZERO_ERROR;
554     std::string result;
555     UnicodeString dateString;
556     calendar->clear();
557     std::string timezoneStr = timeZone.empty() ? LocaleConfig::GetSystemTimezone() : timeZone;
558     auto zone = std::unique_ptr<TimeZone>(TimeZone::createTimeZone(timezoneStr.c_str()));
559     if (zone != nullptr) {
560         calendar->setTimeZone(*zone);
561         dateFormat->setTimeZone(*zone);
562     }
563     calendar->setTime((UDate)milliseconds, status);
564     dateFormat->format(calendar->getTime(status), dateString, status);
565     dateString.toUTF8String(result);
566     return PseudoLocalizationProcessor(result);
567 }
568 
FormatRange(int64_t fromMilliseconds,int64_t toMilliseconds)569 std::string DateTimeFormat::FormatRange(int64_t fromMilliseconds, int64_t toMilliseconds)
570 {
571     if (!createSuccess || calendar == nullptr) {
572         return PseudoLocalizationProcessor("");
573     }
574     UErrorCode status = U_ZERO_ERROR;
575     std::string result;
576     UnicodeString dateString;
577     calendar->clear();
578     std::string timezoneStr = timeZone.empty() ? LocaleConfig::GetSystemTimezone() : timeZone;
579     auto zone = std::unique_ptr<TimeZone>(TimeZone::createTimeZone(timezoneStr.c_str()));
580     if (zone != nullptr) {
581         calendar->setTimeZone(*zone);
582         dateIntvFormat->setTimeZone(*zone);
583     }
584     calendar->setTime((UDate)fromMilliseconds, status);
585 
586     auto toCalendar = std::unique_ptr<Calendar>(Calendar::createInstance(locale, status));
587     if (U_FAILURE(status) || toCalendar == nullptr) {
588         return PseudoLocalizationProcessor("");
589     }
590     toCalendar->clear();
591     if (zone != nullptr) {
592         toCalendar->setTimeZone(*zone);
593     }
594     toCalendar->setTime((UDate)toMilliseconds, status);
595     FieldPosition pos = 0;
596     dateIntvFormat->format(*calendar, *toCalendar, dateString, pos, status);
597     dateString.toUTF8String(result);
598     return PseudoLocalizationProcessor(result);
599 }
600 
GetResolvedOptions(std::map<std::string,std::string> & map)601 void DateTimeFormat::GetResolvedOptions(std::map<std::string, std::string> &map)
602 {
603     map.insert(std::make_pair("locale", localeTag));
604     if (!(localeInfo->GetCalendar()).empty()) {
605         map.insert(std::make_pair("calendar", localeInfo->GetCalendar()));
606     } else {
607         map.insert(std::make_pair("calendar", calendar->getType()));
608     }
609     if (!dateStyle.empty()) {
610         map.insert(std::make_pair("dateStyle", dateStyle));
611     }
612     if (!timeStyle.empty()) {
613         map.insert(std::make_pair("timeStyle", timeStyle));
614     }
615     if (!hourCycle.empty()) {
616         map.insert(std::make_pair("hourCycle", hourCycle));
617     } else if (!(localeInfo->GetHourCycle()).empty()) {
618         map.insert(std::make_pair("hourCycle", localeInfo->GetHourCycle()));
619     }
620     if (!timeZone.empty()) {
621         map.insert(std::make_pair("timeZone", timeZone));
622     } else {
623         UnicodeString timeZoneID("");
624         std::string timeZoneString;
625         dateFormat->getTimeZone().getID(timeZoneID).toUTF8String(timeZoneString);
626         map.insert(std::make_pair("timeZone", timeZoneString));
627     }
628     if (!timeZoneName.empty()) {
629         map.insert(std::make_pair("timeZoneName", timeZoneName));
630     }
631     if (!numberingSystem.empty()) {
632         map.insert(std::make_pair("numberingSystem", numberingSystem));
633     } else if (!(localeInfo->GetNumberingSystem()).empty()) {
634         map.insert(std::make_pair("numberingSystem", localeInfo->GetNumberingSystem()));
635     } else {
636         UErrorCode status = U_ZERO_ERROR;
637         auto numSys = std::unique_ptr<NumberingSystem>(NumberingSystem::createInstance(locale, status));
638         if (U_SUCCESS(status)) {
639             map.insert(std::make_pair("numberingSystem", numSys->getName()));
640         }
641     }
642     GetAdditionalResolvedOptions(map);
643 }
644 
GetAdditionalResolvedOptions(std::map<std::string,std::string> & map)645 void DateTimeFormat::GetAdditionalResolvedOptions(std::map<std::string, std::string> &map)
646 {
647     if (!hour12.empty()) {
648         map.insert(std::make_pair("hour12", hour12));
649     }
650     if (!weekday.empty()) {
651         map.insert(std::make_pair("weekday", weekday));
652     }
653     if (!era.empty()) {
654         map.insert(std::make_pair("era", era));
655     }
656     if (!year.empty()) {
657         map.insert(std::make_pair("year", year));
658     }
659     if (!month.empty()) {
660         map.insert(std::make_pair("month", month));
661     }
662     if (!day.empty()) {
663         map.insert(std::make_pair("day", day));
664     }
665     if (!hour.empty()) {
666         map.insert(std::make_pair("hour", hour));
667     }
668     if (!minute.empty()) {
669         map.insert(std::make_pair("minute", minute));
670     }
671     if (!second.empty()) {
672         map.insert(std::make_pair("second", second));
673     }
674     if (!dayPeriod.empty()) {
675         map.insert(std::make_pair("dayPeriod", dayPeriod));
676     }
677     if (!localeMatcher.empty()) {
678         map.insert(std::make_pair("localeMatcher", localeMatcher));
679     }
680     if (!formatMatcher.empty()) {
681         map.insert(std::make_pair("formatMatcher", formatMatcher));
682     }
683 }
684 
GetDateStyle() const685 std::string DateTimeFormat::GetDateStyle() const
686 {
687     return dateStyle;
688 }
689 
GetTimeStyle() const690 std::string DateTimeFormat::GetTimeStyle() const
691 {
692     return timeStyle;
693 }
694 
GetHourCycle() const695 std::string DateTimeFormat::GetHourCycle() const
696 {
697     return hourCycle;
698 }
699 
GetTimeZone() const700 std::string DateTimeFormat::GetTimeZone() const
701 {
702     return timeZone;
703 }
704 
GetTimeZoneName() const705 std::string DateTimeFormat::GetTimeZoneName() const
706 {
707     return timeZoneName;
708 }
709 
GetNumberingSystem() const710 std::string DateTimeFormat::GetNumberingSystem() const
711 {
712     return numberingSystem;
713 }
714 
GetHour12() const715 std::string DateTimeFormat::GetHour12() const
716 {
717     return hour12;
718 }
719 
GetWeekday() const720 std::string DateTimeFormat::GetWeekday() const
721 {
722     return weekday;
723 }
724 
GetEra() const725 std::string DateTimeFormat::GetEra() const
726 {
727     return era;
728 }
729 
GetYear() const730 std::string DateTimeFormat::GetYear() const
731 {
732     return year;
733 }
734 
GetMonth() const735 std::string DateTimeFormat::GetMonth() const
736 {
737     return month;
738 }
739 
GetDay() const740 std::string DateTimeFormat::GetDay() const
741 {
742     return day;
743 }
744 
GetHour() const745 std::string DateTimeFormat::GetHour() const
746 {
747     return hour;
748 }
749 
GetMinute() const750 std::string DateTimeFormat::GetMinute() const
751 {
752     return minute;
753 }
754 
GetSecond() const755 std::string DateTimeFormat::GetSecond() const
756 {
757     return second;
758 }
759 
Init()760 bool DateTimeFormat::Init()
761 {
762     SetHwIcuDirectory();
763     return true;
764 }
765 
GetDefaultStyle()766 DateTimeFormat::DefaultStyle DateTimeFormat::GetDefaultStyle()
767 {
768     char value[BUFFER_LEN];
769     int code = GetParameter(DEVICE_TYPE_NAME, "", value, BUFFER_LEN);
770     if (code > 0) {
771         std::string deviceType = value;
772         if (DeviceToStyle.find(deviceType) != DeviceToStyle.end()) {
773             return DeviceToStyle[deviceType];
774         }
775     }
776     return DefaultStyle::DEFAULT;
777 }
778 } // namespace I18n
779 } // namespace Global
780 } // namespace OHOS
781