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_sequence.h"
16 #include "i18n_hilog.h"
17 #include "unicode/datefmt.h"
18 #include "unicode/locid.h"
19 #include "unicode/smpdtfmt.h"
20 #include "unicode/dtptngen.h"
21 #include <regex>
22 
23 namespace OHOS {
24 namespace Global {
25 namespace I18n {
26 
27 const std::unordered_map<std::string, std::string> DateTimeSequence::DATE_ORDER_MAP = {
28     { "ug", "L-d-y" },
29     { "ar", "y-L-d" },
30     { "fa", "y-L-d" },
31     { "ur", "y-L-d" },
32     { "iw", "y-L-d" },
33     { "he", "y-L-d" },
34 };
35 
GetDateOrder(const std::string & locale)36 std::string DateTimeSequence::GetDateOrder(const std::string &locale)
37 {
38     UErrorCode icuStatus = U_ZERO_ERROR;
39     icu::Locale localeObj = icu::Locale::forLanguageTag(locale.data(), icuStatus);
40     if (U_FAILURE(icuStatus)) {
41         HILOG_ERROR_I18N("Failed to create locale for GetDateOrder");
42         return "";
43     }
44     const char* language = localeObj.getBaseName();
45     if (language == nullptr) {
46         HILOG_ERROR_I18N("%{public}s getBaseName is null.", locale.c_str());
47         return "";
48     }
49     std::string languageTag = language;
50     if (DATE_ORDER_MAP.find(languageTag) != DATE_ORDER_MAP.end()) {
51         std::string dateOrder = DATE_ORDER_MAP.find(languageTag)->second;
52         return dateOrder;
53     }
54     icu::SimpleDateFormat* formatter = dynamic_cast<icu::SimpleDateFormat*>
55         (icu::DateFormat::createDateInstance(icu::DateFormat::EStyle::kDefault, localeObj));
56     if (U_FAILURE(icuStatus) || formatter == nullptr) {
57         HILOG_ERROR_I18N("Failed to create SimpleDateFormat");
58         return "";
59     }
60     std::string tempValue;
61     icu::UnicodeString unistr;
62     formatter->toPattern(unistr);
63     unistr.toUTF8String<std::string>(tempValue);
64     std::string value = ModifyOrder(tempValue);
65     delete formatter;
66     return value;
67 }
68 
ModifyOrder(std::string & pattern)69 std::string DateTimeSequence::ModifyOrder(std::string &pattern)
70 {
71     int order[3] = { 0 }; // total 3 elements 'y', 'M'/'L', 'd'
72     int lengths[4] = { 0 }; // first elements is the currently found elememnts, thus 4 elements totally.
73     bool flag = true;
74     for (size_t i = 0; i < pattern.length(); ++i) {
75         char ch = pattern[i];
76         if (flag && std::isalpha(ch)) {
77             ProcessNormal(ch, order, 3, lengths, 4); // 3, 4 are lengths of these arrays
78         } else if (ch == '\'') {
79             flag = !flag;
80         }
81     }
82     std::unordered_map<char, int> pattern2index = {
83         { 'y', 1 },
84         { 'L', 2 },
85         { 'd', 3 },
86     };
87     std::string ret;
88     for (int i = 0; i < 3; ++i) { // 3 is the size of orders
89         auto it = pattern2index.find(order[i]);
90         if (it == pattern2index.end()) {
91             continue;
92         }
93         int index = it->second;
94         if ((lengths[index] > 0) && (lengths[index] <= 6)) { // 6 is the max length of a filed
95             ret.append(lengths[index], order[i]);
96         }
97         if (i < 2) { // 2 is the size of the order minus one
98             ret.append(1, '-');
99         }
100     }
101     return ret;
102 }
103 
ProcessNormal(char ch,int * order,size_t orderSize,int * lengths,size_t lengsSize)104 void DateTimeSequence::ProcessNormal(char ch, int *order, size_t orderSize, int *lengths, size_t lengsSize)
105 {
106     char adjust;
107     int index = -1;
108     if (ch == 'd') {
109         adjust = 'd';
110         index = 3; // 3 is the index of 'd'
111     } else if ((ch == 'L') || (ch == 'M')) {
112         adjust = 'L';
113         index = 2; // 2 is the index of 'M'
114     } else if (ch == 'y') {
115         adjust = 'y';
116         index = 1;
117     } else {
118         return;
119     }
120     if ((index < 0) || (index >= static_cast<int>(lengsSize))) {
121         return;
122     }
123     if (lengths[index] == 0) {
124         if (lengths[0] >= 3) { // 3 is the index of order
125             return;
126         }
127         order[lengths[0]] = static_cast<int>(adjust);
128         ++lengths[0];
129         lengths[index] = 1;
130     } else {
131         ++lengths[index];
132     }
133 }
134 
135 } // namespace I18n
136 } // namespace Global
137 } // namespace OHOS