19596a2c1Sopenharmony_ci/*
29596a2c1Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
39596a2c1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
49596a2c1Sopenharmony_ci * you may not use this file except in compliance with the License.
59596a2c1Sopenharmony_ci * You may obtain a copy of the License at
69596a2c1Sopenharmony_ci *
79596a2c1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
89596a2c1Sopenharmony_ci *
99596a2c1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
109596a2c1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
119596a2c1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129596a2c1Sopenharmony_ci * See the License for the specific language governing permissions and
139596a2c1Sopenharmony_ci * limitations under the License.
149596a2c1Sopenharmony_ci */
159596a2c1Sopenharmony_ci#include "i18n_calendar.h"
169596a2c1Sopenharmony_ci
179596a2c1Sopenharmony_ci#include "buddhcal.h"
189596a2c1Sopenharmony_ci#include "chnsecal.h"
199596a2c1Sopenharmony_ci#include "coptccal.h"
209596a2c1Sopenharmony_ci#include "ethpccal.h"
219596a2c1Sopenharmony_ci#include "hebrwcal.h"
229596a2c1Sopenharmony_ci#include "indiancal.h"
239596a2c1Sopenharmony_ci#include "islamcal.h"
249596a2c1Sopenharmony_ci#include "japancal.h"
259596a2c1Sopenharmony_ci#include "unicode/locdspnm.h"
269596a2c1Sopenharmony_ci#include "persncal.h"
279596a2c1Sopenharmony_ci#include "string"
289596a2c1Sopenharmony_ci#include "ureslocs.h"
299596a2c1Sopenharmony_ci#include "ulocimp.h"
309596a2c1Sopenharmony_ci#include "unicode/umachine.h"
319596a2c1Sopenharmony_ci#include "unicode/gregocal.h"
329596a2c1Sopenharmony_ci#include "unicode/timezone.h"
339596a2c1Sopenharmony_ci#include "unicode/unistr.h"
349596a2c1Sopenharmony_ci#include "unicode/urename.h"
359596a2c1Sopenharmony_ci#include "ustr_imp.h"
369596a2c1Sopenharmony_ci#include "unicode/ustring.h"
379596a2c1Sopenharmony_ci#include "utils.h"
389596a2c1Sopenharmony_ci
399596a2c1Sopenharmony_cinamespace OHOS {
409596a2c1Sopenharmony_cinamespace Global {
419596a2c1Sopenharmony_cinamespace I18n {
429596a2c1Sopenharmony_ciI18nCalendar::I18nCalendar(std::string localeTag)
439596a2c1Sopenharmony_ci{
449596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
459596a2c1Sopenharmony_ci    icu::Locale tempLocale = icu::Locale::forLanguageTag(localeTag, status);
469596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
479596a2c1Sopenharmony_ci        calendar_ = new icu::GregorianCalendar(status);
489596a2c1Sopenharmony_ci        if (!U_SUCCESS(status)) {
499596a2c1Sopenharmony_ci            if (calendar_ != nullptr) {
509596a2c1Sopenharmony_ci                delete calendar_;
519596a2c1Sopenharmony_ci            }
529596a2c1Sopenharmony_ci            calendar_ = nullptr;
539596a2c1Sopenharmony_ci        }
549596a2c1Sopenharmony_ci        return;
559596a2c1Sopenharmony_ci    }
569596a2c1Sopenharmony_ci    calendar_ = icu::Calendar::createInstance(tempLocale, status);
579596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
589596a2c1Sopenharmony_ci        if (calendar_ != nullptr) {
599596a2c1Sopenharmony_ci            delete calendar_;
609596a2c1Sopenharmony_ci        }
619596a2c1Sopenharmony_ci        calendar_ = nullptr;
629596a2c1Sopenharmony_ci    }
639596a2c1Sopenharmony_ci}
649596a2c1Sopenharmony_ci
659596a2c1Sopenharmony_ciI18nCalendar::I18nCalendar(std::string localeTag, CalendarType type)
669596a2c1Sopenharmony_ci{
679596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
689596a2c1Sopenharmony_ci    icu::Locale tempLocale = icu::Locale::forLanguageTag(localeTag, status);
699596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
709596a2c1Sopenharmony_ci        calendar_ = new icu::GregorianCalendar(status);
719596a2c1Sopenharmony_ci        if (!U_SUCCESS(status)) {
729596a2c1Sopenharmony_ci            if (calendar_ != nullptr) {
739596a2c1Sopenharmony_ci                delete calendar_;
749596a2c1Sopenharmony_ci            }
759596a2c1Sopenharmony_ci            calendar_ = nullptr;
769596a2c1Sopenharmony_ci        }
779596a2c1Sopenharmony_ci        return;
789596a2c1Sopenharmony_ci    }
799596a2c1Sopenharmony_ci    InitCalendar(tempLocale, type);
809596a2c1Sopenharmony_ci}
819596a2c1Sopenharmony_ci
829596a2c1Sopenharmony_civoid I18nCalendar::InitCalendar(const icu::Locale &locale, CalendarType type)
839596a2c1Sopenharmony_ci{
849596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
859596a2c1Sopenharmony_ci    switch (type) {
869596a2c1Sopenharmony_ci        case BUDDHIST: {
879596a2c1Sopenharmony_ci            calendar_ = new icu::BuddhistCalendar(locale, status);
889596a2c1Sopenharmony_ci            break;
899596a2c1Sopenharmony_ci        }
909596a2c1Sopenharmony_ci        case CHINESE: {
919596a2c1Sopenharmony_ci            calendar_ = new icu::ChineseCalendar(locale, status);
929596a2c1Sopenharmony_ci            break;
939596a2c1Sopenharmony_ci        }
949596a2c1Sopenharmony_ci        case COPTIC: {
959596a2c1Sopenharmony_ci            calendar_ = new icu::CopticCalendar(locale, status);
969596a2c1Sopenharmony_ci            break;
979596a2c1Sopenharmony_ci        }
989596a2c1Sopenharmony_ci        case ETHIOPIC: {
999596a2c1Sopenharmony_ci            calendar_ = new icu::EthiopicCalendar(locale, status);
1009596a2c1Sopenharmony_ci            break;
1019596a2c1Sopenharmony_ci        }
1029596a2c1Sopenharmony_ci        case HEBREW: {
1039596a2c1Sopenharmony_ci            calendar_ = new icu::HebrewCalendar(locale, status);
1049596a2c1Sopenharmony_ci            break;
1059596a2c1Sopenharmony_ci        }
1069596a2c1Sopenharmony_ci        case INDIAN: {
1079596a2c1Sopenharmony_ci            calendar_ = new icu::IndianCalendar(locale, status);
1089596a2c1Sopenharmony_ci            break;
1099596a2c1Sopenharmony_ci        }
1109596a2c1Sopenharmony_ci        case ISLAMIC_CIVIL: {
1119596a2c1Sopenharmony_ci            calendar_ = new icu::IslamicCalendar(locale, status, icu::IslamicCalendar::ECalculationType::CIVIL);
1129596a2c1Sopenharmony_ci            break;
1139596a2c1Sopenharmony_ci        }
1149596a2c1Sopenharmony_ci        default: {
1159596a2c1Sopenharmony_ci            InitCalendar2(locale, type, status);
1169596a2c1Sopenharmony_ci        }
1179596a2c1Sopenharmony_ci    }
1189596a2c1Sopenharmony_ci    if (!U_SUCCESS(status)) {
1199596a2c1Sopenharmony_ci        if (calendar_ != nullptr) {
1209596a2c1Sopenharmony_ci            delete calendar_;
1219596a2c1Sopenharmony_ci        }
1229596a2c1Sopenharmony_ci        calendar_ = nullptr;
1239596a2c1Sopenharmony_ci    }
1249596a2c1Sopenharmony_ci}
1259596a2c1Sopenharmony_ci
1269596a2c1Sopenharmony_civoid I18nCalendar::InitCalendar2(const icu::Locale &locale, CalendarType type, UErrorCode &status)
1279596a2c1Sopenharmony_ci{
1289596a2c1Sopenharmony_ci    switch (type) {
1299596a2c1Sopenharmony_ci        case ISLAMIC_TBLA: {
1309596a2c1Sopenharmony_ci            calendar_ = new icu::IslamicCalendar(locale, status, icu::IslamicCalendar::ECalculationType::TBLA);
1319596a2c1Sopenharmony_ci            break;
1329596a2c1Sopenharmony_ci        }
1339596a2c1Sopenharmony_ci        case ISLAMIC_UMALQURA: {
1349596a2c1Sopenharmony_ci            calendar_ = new icu::IslamicCalendar(locale, status, icu::IslamicCalendar::ECalculationType::UMALQURA);
1359596a2c1Sopenharmony_ci            break;
1369596a2c1Sopenharmony_ci        }
1379596a2c1Sopenharmony_ci        case JAPANESE: {
1389596a2c1Sopenharmony_ci            calendar_ = new icu::JapaneseCalendar(locale, status);
1399596a2c1Sopenharmony_ci            break;
1409596a2c1Sopenharmony_ci        }
1419596a2c1Sopenharmony_ci        case PERSIAN: {
1429596a2c1Sopenharmony_ci            calendar_ = new icu::PersianCalendar(locale, status);
1439596a2c1Sopenharmony_ci            break;
1449596a2c1Sopenharmony_ci        }
1459596a2c1Sopenharmony_ci        case GREGORY: {
1469596a2c1Sopenharmony_ci            calendar_ = new icu::GregorianCalendar(locale, status);
1479596a2c1Sopenharmony_ci            break;
1489596a2c1Sopenharmony_ci        }
1499596a2c1Sopenharmony_ci        default: {
1509596a2c1Sopenharmony_ci            calendar_ = icu::Calendar::createInstance(locale, status);
1519596a2c1Sopenharmony_ci        }
1529596a2c1Sopenharmony_ci    }
1539596a2c1Sopenharmony_ci}
1549596a2c1Sopenharmony_ci
1559596a2c1Sopenharmony_ciI18nCalendar::~I18nCalendar()
1569596a2c1Sopenharmony_ci{
1579596a2c1Sopenharmony_ci    if (calendar_ != nullptr) {
1589596a2c1Sopenharmony_ci        delete calendar_;
1599596a2c1Sopenharmony_ci    }
1609596a2c1Sopenharmony_ci}
1619596a2c1Sopenharmony_ci
1629596a2c1Sopenharmony_civoid I18nCalendar::SetTime(double value)
1639596a2c1Sopenharmony_ci{
1649596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
1659596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
1669596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
1679596a2c1Sopenharmony_ci        icuCalendar->setTime(value, status);
1689596a2c1Sopenharmony_ci        return;
1699596a2c1Sopenharmony_ci    }
1709596a2c1Sopenharmony_ci}
1719596a2c1Sopenharmony_ci
1729596a2c1Sopenharmony_civoid I18nCalendar::SetTimeZone(std::string id)
1739596a2c1Sopenharmony_ci{
1749596a2c1Sopenharmony_ci    icu::UnicodeString zone = icu::UnicodeString::fromUTF8(id);
1759596a2c1Sopenharmony_ci    icu::TimeZone *timezone = icu::TimeZone::createTimeZone(zone);
1769596a2c1Sopenharmony_ci    if (timezone != nullptr) {
1779596a2c1Sopenharmony_ci        icu::Calendar* icuCalendar = GetIcuCalendar();
1789596a2c1Sopenharmony_ci        if (icuCalendar != nullptr) {
1799596a2c1Sopenharmony_ci            icuCalendar->setTimeZone(*timezone);
1809596a2c1Sopenharmony_ci        }
1819596a2c1Sopenharmony_ci        delete(timezone);
1829596a2c1Sopenharmony_ci    }
1839596a2c1Sopenharmony_ci}
1849596a2c1Sopenharmony_ci
1859596a2c1Sopenharmony_cistd::string I18nCalendar::GetTimeZone(void)
1869596a2c1Sopenharmony_ci{
1879596a2c1Sopenharmony_ci    std::string ret;
1889596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
1899596a2c1Sopenharmony_ci    if (icuCalendar) {
1909596a2c1Sopenharmony_ci        icu::UnicodeString unistr;
1919596a2c1Sopenharmony_ci        icuCalendar->getTimeZone().getID(unistr);
1929596a2c1Sopenharmony_ci        unistr.toUTF8String<std::string>(ret);
1939596a2c1Sopenharmony_ci    }
1949596a2c1Sopenharmony_ci    return ret;
1959596a2c1Sopenharmony_ci}
1969596a2c1Sopenharmony_ci
1979596a2c1Sopenharmony_civoid I18nCalendar::Set(int32_t year, int32_t month, int32_t date)
1989596a2c1Sopenharmony_ci{
1999596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2009596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2019596a2c1Sopenharmony_ci        icuCalendar->set(year, month, date);
2029596a2c1Sopenharmony_ci        return;
2039596a2c1Sopenharmony_ci    }
2049596a2c1Sopenharmony_ci}
2059596a2c1Sopenharmony_ci
2069596a2c1Sopenharmony_civoid I18nCalendar::Set(UCalendarDateFields field, int32_t value)
2079596a2c1Sopenharmony_ci{
2089596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2099596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2109596a2c1Sopenharmony_ci        icuCalendar->set(field, value);
2119596a2c1Sopenharmony_ci        return;
2129596a2c1Sopenharmony_ci    }
2139596a2c1Sopenharmony_ci}
2149596a2c1Sopenharmony_ci
2159596a2c1Sopenharmony_ciint32_t I18nCalendar::Get(UCalendarDateFields field) const
2169596a2c1Sopenharmony_ci{
2179596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2189596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2199596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
2209596a2c1Sopenharmony_ci        return icuCalendar->get(field, status);
2219596a2c1Sopenharmony_ci    }
2229596a2c1Sopenharmony_ci    return 0;
2239596a2c1Sopenharmony_ci}
2249596a2c1Sopenharmony_ci
2259596a2c1Sopenharmony_civoid I18nCalendar::Add(UCalendarDateFields field, int32_t amount)
2269596a2c1Sopenharmony_ci{
2279596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2289596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2299596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
2309596a2c1Sopenharmony_ci        icuCalendar->add(field, amount, status);
2319596a2c1Sopenharmony_ci    }
2329596a2c1Sopenharmony_ci}
2339596a2c1Sopenharmony_ci
2349596a2c1Sopenharmony_civoid I18nCalendar::SetMinimalDaysInFirstWeek(int32_t value)
2359596a2c1Sopenharmony_ci{
2369596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2379596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2389596a2c1Sopenharmony_ci        icuCalendar->setMinimalDaysInFirstWeek((uint8_t)value);
2399596a2c1Sopenharmony_ci        return;
2409596a2c1Sopenharmony_ci    }
2419596a2c1Sopenharmony_ci}
2429596a2c1Sopenharmony_ci
2439596a2c1Sopenharmony_civoid I18nCalendar::SetFirstDayOfWeek(int32_t value)
2449596a2c1Sopenharmony_ci{
2459596a2c1Sopenharmony_ci    if (value < UCalendarDaysOfWeek::UCAL_SUNDAY || value > UCAL_SATURDAY) {
2469596a2c1Sopenharmony_ci        return;
2479596a2c1Sopenharmony_ci    }
2489596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2499596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2509596a2c1Sopenharmony_ci        icuCalendar->setFirstDayOfWeek(UCalendarDaysOfWeek(value));
2519596a2c1Sopenharmony_ci        return;
2529596a2c1Sopenharmony_ci    }
2539596a2c1Sopenharmony_ci}
2549596a2c1Sopenharmony_ci
2559596a2c1Sopenharmony_ciUDate I18nCalendar::GetTimeInMillis(void)
2569596a2c1Sopenharmony_ci{
2579596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2589596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2599596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
2609596a2c1Sopenharmony_ci        return icuCalendar->getTime(status);
2619596a2c1Sopenharmony_ci    }
2629596a2c1Sopenharmony_ci    return 0;
2639596a2c1Sopenharmony_ci}
2649596a2c1Sopenharmony_ci
2659596a2c1Sopenharmony_ciint32_t I18nCalendar::GetMinimalDaysInFirstWeek(void)
2669596a2c1Sopenharmony_ci{
2679596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2689596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2699596a2c1Sopenharmony_ci        return icuCalendar->getMinimalDaysInFirstWeek();
2709596a2c1Sopenharmony_ci    }
2719596a2c1Sopenharmony_ci    return 1;
2729596a2c1Sopenharmony_ci}
2739596a2c1Sopenharmony_ci
2749596a2c1Sopenharmony_ciint32_t I18nCalendar::GetFirstDayOfWeek(void)
2759596a2c1Sopenharmony_ci{
2769596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2779596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2789596a2c1Sopenharmony_ci        return static_cast<int>(icuCalendar->getFirstDayOfWeek());
2799596a2c1Sopenharmony_ci    }
2809596a2c1Sopenharmony_ci    return UCAL_SUNDAY;
2819596a2c1Sopenharmony_ci}
2829596a2c1Sopenharmony_ci
2839596a2c1Sopenharmony_cibool I18nCalendar::IsWeekend(int64_t date, UErrorCode &status)
2849596a2c1Sopenharmony_ci{
2859596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2869596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2879596a2c1Sopenharmony_ci        return icuCalendar->isWeekend(date, status);
2889596a2c1Sopenharmony_ci    }
2899596a2c1Sopenharmony_ci    return false;
2909596a2c1Sopenharmony_ci}
2919596a2c1Sopenharmony_ci
2929596a2c1Sopenharmony_cibool I18nCalendar::IsWeekend(void)
2939596a2c1Sopenharmony_ci{
2949596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
2959596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
2969596a2c1Sopenharmony_ci        return icuCalendar->isWeekend();
2979596a2c1Sopenharmony_ci    }
2989596a2c1Sopenharmony_ci    return false;
2999596a2c1Sopenharmony_ci}
3009596a2c1Sopenharmony_ci
3019596a2c1Sopenharmony_cistd::string I18nCalendar::GetDisplayName(std::string &displayLocaleTag)
3029596a2c1Sopenharmony_ci{
3039596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
3049596a2c1Sopenharmony_ci    if (icuCalendar == nullptr) {
3059596a2c1Sopenharmony_ci        return PseudoLocalizationProcessor("");
3069596a2c1Sopenharmony_ci    }
3079596a2c1Sopenharmony_ci    const char *type = icuCalendar->getType();
3089596a2c1Sopenharmony_ci    if (type == nullptr) {
3099596a2c1Sopenharmony_ci        return PseudoLocalizationProcessor("");
3109596a2c1Sopenharmony_ci    }
3119596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
3129596a2c1Sopenharmony_ci    icu::Locale displayLocale = icu::Locale::forLanguageTag(displayLocaleTag, status);
3139596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
3149596a2c1Sopenharmony_ci        return PseudoLocalizationProcessor("");
3159596a2c1Sopenharmony_ci    }
3169596a2c1Sopenharmony_ci    icu::LocaleDisplayNames *dspName = icu::LocaleDisplayNames::createInstance(displayLocale);
3179596a2c1Sopenharmony_ci    icu::UnicodeString unistr;
3189596a2c1Sopenharmony_ci    if (dspName != nullptr) {
3199596a2c1Sopenharmony_ci        dspName->keyValueDisplayName("calendar", type, unistr);
3209596a2c1Sopenharmony_ci        delete dspName;
3219596a2c1Sopenharmony_ci    }
3229596a2c1Sopenharmony_ci    std::string ret;
3239596a2c1Sopenharmony_ci    unistr.toUTF8String<std::string>(ret);
3249596a2c1Sopenharmony_ci    return PseudoLocalizationProcessor(ret);
3259596a2c1Sopenharmony_ci}
3269596a2c1Sopenharmony_ci
3279596a2c1Sopenharmony_ciint32_t I18nCalendar::CompareDays(UDate date)
3289596a2c1Sopenharmony_ci{
3299596a2c1Sopenharmony_ci    icu::Calendar* icuCalendar = GetIcuCalendar();
3309596a2c1Sopenharmony_ci    if (icuCalendar != nullptr) {
3319596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
3329596a2c1Sopenharmony_ci        UDate nowMs = icuCalendar->getTime(status);
3339596a2c1Sopenharmony_ci        double ret = (date - nowMs) / (24 * 60 * 60 * 1000); // Convert 24 hours into milliseconds
3349596a2c1Sopenharmony_ci        return ret > 0 ? std::ceil(ret) : std::floor(ret);
3359596a2c1Sopenharmony_ci    }
3369596a2c1Sopenharmony_ci    return 0;
3379596a2c1Sopenharmony_ci}
3389596a2c1Sopenharmony_ci
3399596a2c1Sopenharmony_ciicu::Calendar* I18nCalendar::GetIcuCalendar() const
3409596a2c1Sopenharmony_ci{
3419596a2c1Sopenharmony_ci    return this->calendar_;
3429596a2c1Sopenharmony_ci}
3439596a2c1Sopenharmony_ci} // namespace I18n
3449596a2c1Sopenharmony_ci} // namespace Global
3459596a2c1Sopenharmony_ci} // namespace OHOS