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