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 "i18n_calendar.h"
16
17 #include "buddhcal.h"
18 #include "chnsecal.h"
19 #include "coptccal.h"
20 #include "ethpccal.h"
21 #include "hebrwcal.h"
22 #include "indiancal.h"
23 #include "islamcal.h"
24 #include "japancal.h"
25 #include "unicode/locdspnm.h"
26 #include "persncal.h"
27 #include "string"
28 #include "ureslocs.h"
29 #include "ulocimp.h"
30 #include "unicode/umachine.h"
31 #include "unicode/gregocal.h"
32 #include "unicode/timezone.h"
33 #include "unicode/unistr.h"
34 #include "unicode/urename.h"
35 #include "ustr_imp.h"
36 #include "unicode/ustring.h"
37 #include "utils.h"
38
39 namespace OHOS {
40 namespace Global {
41 namespace I18n {
I18nCalendar(std::string localeTag)42 I18nCalendar::I18nCalendar(std::string localeTag)
43 {
44 UErrorCode status = U_ZERO_ERROR;
45 icu::Locale tempLocale = icu::Locale::forLanguageTag(localeTag, status);
46 if (status != U_ZERO_ERROR) {
47 calendar_ = new icu::GregorianCalendar(status);
48 if (!U_SUCCESS(status)) {
49 if (calendar_ != nullptr) {
50 delete calendar_;
51 }
52 calendar_ = nullptr;
53 }
54 return;
55 }
56 calendar_ = icu::Calendar::createInstance(tempLocale, status);
57 if (status != U_ZERO_ERROR) {
58 if (calendar_ != nullptr) {
59 delete calendar_;
60 }
61 calendar_ = nullptr;
62 }
63 }
64
I18nCalendar(std::string localeTag,CalendarType type)65 I18nCalendar::I18nCalendar(std::string localeTag, CalendarType type)
66 {
67 UErrorCode status = U_ZERO_ERROR;
68 icu::Locale tempLocale = icu::Locale::forLanguageTag(localeTag, status);
69 if (status != U_ZERO_ERROR) {
70 calendar_ = new icu::GregorianCalendar(status);
71 if (!U_SUCCESS(status)) {
72 if (calendar_ != nullptr) {
73 delete calendar_;
74 }
75 calendar_ = nullptr;
76 }
77 return;
78 }
79 InitCalendar(tempLocale, type);
80 }
81
InitCalendar(const icu::Locale & locale,CalendarType type)82 void I18nCalendar::InitCalendar(const icu::Locale &locale, CalendarType type)
83 {
84 UErrorCode status = U_ZERO_ERROR;
85 switch (type) {
86 case BUDDHIST: {
87 calendar_ = new icu::BuddhistCalendar(locale, status);
88 break;
89 }
90 case CHINESE: {
91 calendar_ = new icu::ChineseCalendar(locale, status);
92 break;
93 }
94 case COPTIC: {
95 calendar_ = new icu::CopticCalendar(locale, status);
96 break;
97 }
98 case ETHIOPIC: {
99 calendar_ = new icu::EthiopicCalendar(locale, status);
100 break;
101 }
102 case HEBREW: {
103 calendar_ = new icu::HebrewCalendar(locale, status);
104 break;
105 }
106 case INDIAN: {
107 calendar_ = new icu::IndianCalendar(locale, status);
108 break;
109 }
110 case ISLAMIC_CIVIL: {
111 calendar_ = new icu::IslamicCalendar(locale, status, icu::IslamicCalendar::ECalculationType::CIVIL);
112 break;
113 }
114 default: {
115 InitCalendar2(locale, type, status);
116 }
117 }
118 if (!U_SUCCESS(status)) {
119 if (calendar_ != nullptr) {
120 delete calendar_;
121 }
122 calendar_ = nullptr;
123 }
124 }
125
InitCalendar2(const icu::Locale & locale,CalendarType type,UErrorCode & status)126 void I18nCalendar::InitCalendar2(const icu::Locale &locale, CalendarType type, UErrorCode &status)
127 {
128 switch (type) {
129 case ISLAMIC_TBLA: {
130 calendar_ = new icu::IslamicCalendar(locale, status, icu::IslamicCalendar::ECalculationType::TBLA);
131 break;
132 }
133 case ISLAMIC_UMALQURA: {
134 calendar_ = new icu::IslamicCalendar(locale, status, icu::IslamicCalendar::ECalculationType::UMALQURA);
135 break;
136 }
137 case JAPANESE: {
138 calendar_ = new icu::JapaneseCalendar(locale, status);
139 break;
140 }
141 case PERSIAN: {
142 calendar_ = new icu::PersianCalendar(locale, status);
143 break;
144 }
145 case GREGORY: {
146 calendar_ = new icu::GregorianCalendar(locale, status);
147 break;
148 }
149 default: {
150 calendar_ = icu::Calendar::createInstance(locale, status);
151 }
152 }
153 }
154
~I18nCalendar()155 I18nCalendar::~I18nCalendar()
156 {
157 if (calendar_ != nullptr) {
158 delete calendar_;
159 }
160 }
161
SetTime(double value)162 void I18nCalendar::SetTime(double value)
163 {
164 icu::Calendar* icuCalendar = GetIcuCalendar();
165 if (icuCalendar != nullptr) {
166 UErrorCode status = U_ZERO_ERROR;
167 icuCalendar->setTime(value, status);
168 return;
169 }
170 }
171
SetTimeZone(std::string id)172 void I18nCalendar::SetTimeZone(std::string id)
173 {
174 icu::UnicodeString zone = icu::UnicodeString::fromUTF8(id);
175 icu::TimeZone *timezone = icu::TimeZone::createTimeZone(zone);
176 if (timezone != nullptr) {
177 icu::Calendar* icuCalendar = GetIcuCalendar();
178 if (icuCalendar != nullptr) {
179 icuCalendar->setTimeZone(*timezone);
180 }
181 delete(timezone);
182 }
183 }
184
GetTimeZone(void)185 std::string I18nCalendar::GetTimeZone(void)
186 {
187 std::string ret;
188 icu::Calendar* icuCalendar = GetIcuCalendar();
189 if (icuCalendar) {
190 icu::UnicodeString unistr;
191 icuCalendar->getTimeZone().getID(unistr);
192 unistr.toUTF8String<std::string>(ret);
193 }
194 return ret;
195 }
196
Set(int32_t year,int32_t month,int32_t date)197 void I18nCalendar::Set(int32_t year, int32_t month, int32_t date)
198 {
199 icu::Calendar* icuCalendar = GetIcuCalendar();
200 if (icuCalendar != nullptr) {
201 icuCalendar->set(year, month, date);
202 return;
203 }
204 }
205
Set(UCalendarDateFields field,int32_t value)206 void I18nCalendar::Set(UCalendarDateFields field, int32_t value)
207 {
208 icu::Calendar* icuCalendar = GetIcuCalendar();
209 if (icuCalendar != nullptr) {
210 icuCalendar->set(field, value);
211 return;
212 }
213 }
214
Get(UCalendarDateFields field) const215 int32_t I18nCalendar::Get(UCalendarDateFields field) const
216 {
217 icu::Calendar* icuCalendar = GetIcuCalendar();
218 if (icuCalendar != nullptr) {
219 UErrorCode status = U_ZERO_ERROR;
220 return icuCalendar->get(field, status);
221 }
222 return 0;
223 }
224
Add(UCalendarDateFields field,int32_t amount)225 void I18nCalendar::Add(UCalendarDateFields field, int32_t amount)
226 {
227 icu::Calendar* icuCalendar = GetIcuCalendar();
228 if (icuCalendar != nullptr) {
229 UErrorCode status = U_ZERO_ERROR;
230 icuCalendar->add(field, amount, status);
231 }
232 }
233
SetMinimalDaysInFirstWeek(int32_t value)234 void I18nCalendar::SetMinimalDaysInFirstWeek(int32_t value)
235 {
236 icu::Calendar* icuCalendar = GetIcuCalendar();
237 if (icuCalendar != nullptr) {
238 icuCalendar->setMinimalDaysInFirstWeek((uint8_t)value);
239 return;
240 }
241 }
242
SetFirstDayOfWeek(int32_t value)243 void I18nCalendar::SetFirstDayOfWeek(int32_t value)
244 {
245 if (value < UCalendarDaysOfWeek::UCAL_SUNDAY || value > UCAL_SATURDAY) {
246 return;
247 }
248 icu::Calendar* icuCalendar = GetIcuCalendar();
249 if (icuCalendar != nullptr) {
250 icuCalendar->setFirstDayOfWeek(UCalendarDaysOfWeek(value));
251 return;
252 }
253 }
254
GetTimeInMillis(void)255 UDate I18nCalendar::GetTimeInMillis(void)
256 {
257 icu::Calendar* icuCalendar = GetIcuCalendar();
258 if (icuCalendar != nullptr) {
259 UErrorCode status = U_ZERO_ERROR;
260 return icuCalendar->getTime(status);
261 }
262 return 0;
263 }
264
GetMinimalDaysInFirstWeek(void)265 int32_t I18nCalendar::GetMinimalDaysInFirstWeek(void)
266 {
267 icu::Calendar* icuCalendar = GetIcuCalendar();
268 if (icuCalendar != nullptr) {
269 return icuCalendar->getMinimalDaysInFirstWeek();
270 }
271 return 1;
272 }
273
GetFirstDayOfWeek(void)274 int32_t I18nCalendar::GetFirstDayOfWeek(void)
275 {
276 icu::Calendar* icuCalendar = GetIcuCalendar();
277 if (icuCalendar != nullptr) {
278 return static_cast<int>(icuCalendar->getFirstDayOfWeek());
279 }
280 return UCAL_SUNDAY;
281 }
282
IsWeekend(int64_t date,UErrorCode & status)283 bool I18nCalendar::IsWeekend(int64_t date, UErrorCode &status)
284 {
285 icu::Calendar* icuCalendar = GetIcuCalendar();
286 if (icuCalendar != nullptr) {
287 return icuCalendar->isWeekend(date, status);
288 }
289 return false;
290 }
291
IsWeekend(void)292 bool I18nCalendar::IsWeekend(void)
293 {
294 icu::Calendar* icuCalendar = GetIcuCalendar();
295 if (icuCalendar != nullptr) {
296 return icuCalendar->isWeekend();
297 }
298 return false;
299 }
300
GetDisplayName(std::string & displayLocaleTag)301 std::string I18nCalendar::GetDisplayName(std::string &displayLocaleTag)
302 {
303 icu::Calendar* icuCalendar = GetIcuCalendar();
304 if (icuCalendar == nullptr) {
305 return PseudoLocalizationProcessor("");
306 }
307 const char *type = icuCalendar->getType();
308 if (type == nullptr) {
309 return PseudoLocalizationProcessor("");
310 }
311 UErrorCode status = U_ZERO_ERROR;
312 icu::Locale displayLocale = icu::Locale::forLanguageTag(displayLocaleTag, status);
313 if (status != U_ZERO_ERROR) {
314 return PseudoLocalizationProcessor("");
315 }
316 icu::LocaleDisplayNames *dspName = icu::LocaleDisplayNames::createInstance(displayLocale);
317 icu::UnicodeString unistr;
318 if (dspName != nullptr) {
319 dspName->keyValueDisplayName("calendar", type, unistr);
320 delete dspName;
321 }
322 std::string ret;
323 unistr.toUTF8String<std::string>(ret);
324 return PseudoLocalizationProcessor(ret);
325 }
326
CompareDays(UDate date)327 int32_t I18nCalendar::CompareDays(UDate date)
328 {
329 icu::Calendar* icuCalendar = GetIcuCalendar();
330 if (icuCalendar != nullptr) {
331 UErrorCode status = U_ZERO_ERROR;
332 UDate nowMs = icuCalendar->getTime(status);
333 double ret = (date - nowMs) / (24 * 60 * 60 * 1000); // Convert 24 hours into milliseconds
334 return ret > 0 ? std::ceil(ret) : std::floor(ret);
335 }
336 return 0;
337 }
338
GetIcuCalendar() const339 icu::Calendar* I18nCalendar::GetIcuCalendar() const
340 {
341 return this->calendar_;
342 }
343 } // namespace I18n
344 } // namespace Global
345 } // namespace OHOS