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