11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
31cb0ef41Sopenharmony_ci/*
41cb0ef41Sopenharmony_ci*******************************************************************************
51cb0ef41Sopenharmony_ci*   Copyright (C) 1996-2016, International Business Machines
61cb0ef41Sopenharmony_ci*   Corporation and others.  All Rights Reserved.
71cb0ef41Sopenharmony_ci*******************************************************************************
81cb0ef41Sopenharmony_ci*/
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "utypeinfo.h"  // for 'typeid' to work
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include "unicode/utypes.h"
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci#if !UCONFIG_NO_FORMATTING
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci#include "unicode/ucal.h"
171cb0ef41Sopenharmony_ci#include "unicode/uloc.h"
181cb0ef41Sopenharmony_ci#include "unicode/calendar.h"
191cb0ef41Sopenharmony_ci#include "unicode/timezone.h"
201cb0ef41Sopenharmony_ci#include "unicode/gregocal.h"
211cb0ef41Sopenharmony_ci#include "unicode/simpletz.h"
221cb0ef41Sopenharmony_ci#include "unicode/ustring.h"
231cb0ef41Sopenharmony_ci#include "unicode/strenum.h"
241cb0ef41Sopenharmony_ci#include "unicode/localpointer.h"
251cb0ef41Sopenharmony_ci#include "cmemory.h"
261cb0ef41Sopenharmony_ci#include "cstring.h"
271cb0ef41Sopenharmony_ci#include "iso8601cal.h"
281cb0ef41Sopenharmony_ci#include "ustrenum.h"
291cb0ef41Sopenharmony_ci#include "uenumimp.h"
301cb0ef41Sopenharmony_ci#include "ulist.h"
311cb0ef41Sopenharmony_ci#include "ulocimp.h"
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciU_NAMESPACE_USE
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cistatic TimeZone*
361cb0ef41Sopenharmony_ci_createTimeZone(const char16_t* zoneID, int32_t len, UErrorCode* ec) {
371cb0ef41Sopenharmony_ci    TimeZone* zone = nullptr;
381cb0ef41Sopenharmony_ci    if (ec != nullptr && U_SUCCESS(*ec)) {
391cb0ef41Sopenharmony_ci        // Note that if zoneID is invalid, we get back GMT. This odd
401cb0ef41Sopenharmony_ci        // behavior is by design and goes back to the JDK. The only
411cb0ef41Sopenharmony_ci        // failure we will see is a memory allocation failure.
421cb0ef41Sopenharmony_ci        int32_t l = (len<0 ? u_strlen(zoneID) : len);
431cb0ef41Sopenharmony_ci        UnicodeString zoneStrID;
441cb0ef41Sopenharmony_ci        zoneStrID.setTo((UBool)(len < 0), zoneID, l); /* temporary read-only alias */
451cb0ef41Sopenharmony_ci        zone = TimeZone::createTimeZone(zoneStrID);
461cb0ef41Sopenharmony_ci        if (zone == nullptr) {
471cb0ef41Sopenharmony_ci            *ec = U_MEMORY_ALLOCATION_ERROR;
481cb0ef41Sopenharmony_ci        }
491cb0ef41Sopenharmony_ci    }
501cb0ef41Sopenharmony_ci    return zone;
511cb0ef41Sopenharmony_ci}
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciU_CAPI UEnumeration* U_EXPORT2
541cb0ef41Sopenharmony_ciucal_openTimeZoneIDEnumeration(USystemTimeZoneType zoneType, const char* region,
551cb0ef41Sopenharmony_ci                                const int32_t* rawOffset, UErrorCode* ec) {
561cb0ef41Sopenharmony_ci    return uenum_openFromStringEnumeration(TimeZone::createTimeZoneIDEnumeration(
571cb0ef41Sopenharmony_ci        zoneType, region, rawOffset, *ec), ec);
581cb0ef41Sopenharmony_ci}
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ciU_CAPI UEnumeration* U_EXPORT2
611cb0ef41Sopenharmony_ciucal_openTimeZones(UErrorCode* ec) {
621cb0ef41Sopenharmony_ci    return ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, nullptr, nullptr, ec);
631cb0ef41Sopenharmony_ci}
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ciU_CAPI UEnumeration* U_EXPORT2
661cb0ef41Sopenharmony_ciucal_openCountryTimeZones(const char* country, UErrorCode* ec) {
671cb0ef41Sopenharmony_ci    return ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, country, nullptr, ec);
681cb0ef41Sopenharmony_ci}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
711cb0ef41Sopenharmony_ciucal_getDefaultTimeZone(char16_t* result, int32_t resultCapacity, UErrorCode* ec) {
721cb0ef41Sopenharmony_ci    int32_t len = 0;
731cb0ef41Sopenharmony_ci    if (ec != nullptr && U_SUCCESS(*ec)) {
741cb0ef41Sopenharmony_ci        TimeZone* zone = TimeZone::createDefault();
751cb0ef41Sopenharmony_ci        if (zone == nullptr) {
761cb0ef41Sopenharmony_ci            *ec = U_MEMORY_ALLOCATION_ERROR;
771cb0ef41Sopenharmony_ci        } else {
781cb0ef41Sopenharmony_ci            UnicodeString id;
791cb0ef41Sopenharmony_ci            zone->getID(id);
801cb0ef41Sopenharmony_ci            delete zone;
811cb0ef41Sopenharmony_ci            len = id.extract(result, resultCapacity, *ec);
821cb0ef41Sopenharmony_ci        }
831cb0ef41Sopenharmony_ci    }
841cb0ef41Sopenharmony_ci    return len;
851cb0ef41Sopenharmony_ci}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
881cb0ef41Sopenharmony_ciucal_setDefaultTimeZone(const char16_t* zoneID, UErrorCode* ec) {
891cb0ef41Sopenharmony_ci    TimeZone* zone = _createTimeZone(zoneID, -1, ec);
901cb0ef41Sopenharmony_ci    if (zone != nullptr) {
911cb0ef41Sopenharmony_ci        TimeZone::adoptDefault(zone);
921cb0ef41Sopenharmony_ci    }
931cb0ef41Sopenharmony_ci}
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
961cb0ef41Sopenharmony_ciucal_getHostTimeZone(char16_t* result, int32_t resultCapacity, UErrorCode* ec) {
971cb0ef41Sopenharmony_ci    int32_t len = 0;
981cb0ef41Sopenharmony_ci    if (ec != nullptr && U_SUCCESS(*ec)) {
991cb0ef41Sopenharmony_ci        TimeZone *zone = TimeZone::detectHostTimeZone();
1001cb0ef41Sopenharmony_ci        if (zone == nullptr) {
1011cb0ef41Sopenharmony_ci            *ec = U_MEMORY_ALLOCATION_ERROR;
1021cb0ef41Sopenharmony_ci        } else {
1031cb0ef41Sopenharmony_ci            UnicodeString id;
1041cb0ef41Sopenharmony_ci            zone->getID(id);
1051cb0ef41Sopenharmony_ci            delete zone;
1061cb0ef41Sopenharmony_ci            len = id.extract(result, resultCapacity, *ec);
1071cb0ef41Sopenharmony_ci        }
1081cb0ef41Sopenharmony_ci    }
1091cb0ef41Sopenharmony_ci    return len;
1101cb0ef41Sopenharmony_ci}
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
1131cb0ef41Sopenharmony_ciucal_getDSTSavings(const char16_t* zoneID, UErrorCode* ec) {
1141cb0ef41Sopenharmony_ci    int32_t result = 0;
1151cb0ef41Sopenharmony_ci    TimeZone* zone = _createTimeZone(zoneID, -1, ec);
1161cb0ef41Sopenharmony_ci    if (U_SUCCESS(*ec)) {
1171cb0ef41Sopenharmony_ci        SimpleTimeZone* stz = dynamic_cast<SimpleTimeZone*>(zone);
1181cb0ef41Sopenharmony_ci        if (stz != nullptr) {
1191cb0ef41Sopenharmony_ci            result = stz->getDSTSavings();
1201cb0ef41Sopenharmony_ci        } else {
1211cb0ef41Sopenharmony_ci            // Since there is no getDSTSavings on TimeZone, we use a
1221cb0ef41Sopenharmony_ci            // heuristic: Starting with the current time, march
1231cb0ef41Sopenharmony_ci            // forwards for one year, looking for DST savings.
1241cb0ef41Sopenharmony_ci            // Stepping by weeks is sufficient.
1251cb0ef41Sopenharmony_ci            UDate d = Calendar::getNow();
1261cb0ef41Sopenharmony_ci            for (int32_t i=0; i<53; ++i, d+=U_MILLIS_PER_DAY*7.0) {
1271cb0ef41Sopenharmony_ci                int32_t raw, dst;
1281cb0ef41Sopenharmony_ci                zone->getOffset(d, false, raw, dst, *ec);
1291cb0ef41Sopenharmony_ci                if (U_FAILURE(*ec)) {
1301cb0ef41Sopenharmony_ci                    break;
1311cb0ef41Sopenharmony_ci                } else if (dst != 0) {
1321cb0ef41Sopenharmony_ci                    result = dst;
1331cb0ef41Sopenharmony_ci                    break;
1341cb0ef41Sopenharmony_ci                }
1351cb0ef41Sopenharmony_ci            }
1361cb0ef41Sopenharmony_ci        }
1371cb0ef41Sopenharmony_ci    }
1381cb0ef41Sopenharmony_ci    delete zone;
1391cb0ef41Sopenharmony_ci    return result;
1401cb0ef41Sopenharmony_ci}
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ciU_CAPI UDate  U_EXPORT2
1431cb0ef41Sopenharmony_ciucal_getNow()
1441cb0ef41Sopenharmony_ci{
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  return Calendar::getNow();
1471cb0ef41Sopenharmony_ci}
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci#define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWORD_AND_VALUES_CAPACITY)
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ciU_CAPI UCalendar*  U_EXPORT2
1521cb0ef41Sopenharmony_ciucal_open(  const char16_t*  zoneID,
1531cb0ef41Sopenharmony_ci            int32_t       len,
1541cb0ef41Sopenharmony_ci            const char*   locale,
1551cb0ef41Sopenharmony_ci            UCalendarType caltype,
1561cb0ef41Sopenharmony_ci            UErrorCode*   status)
1571cb0ef41Sopenharmony_ci{
1581cb0ef41Sopenharmony_ci  if (U_FAILURE(*status)) {
1591cb0ef41Sopenharmony_ci      return nullptr;
1601cb0ef41Sopenharmony_ci  }
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  LocalPointer<TimeZone> zone( (zoneID==nullptr) ? TimeZone::createDefault()
1631cb0ef41Sopenharmony_ci      : _createTimeZone(zoneID, len, status), *status);
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci  if (U_FAILURE(*status)) {
1661cb0ef41Sopenharmony_ci      return nullptr;
1671cb0ef41Sopenharmony_ci  }
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  if ( caltype == UCAL_GREGORIAN ) {
1701cb0ef41Sopenharmony_ci      char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY];
1711cb0ef41Sopenharmony_ci      if ( locale == nullptr ) {
1721cb0ef41Sopenharmony_ci          locale = uloc_getDefault();
1731cb0ef41Sopenharmony_ci      }
1741cb0ef41Sopenharmony_ci      int32_t localeLength = static_cast<int32_t>(uprv_strlen(locale));
1751cb0ef41Sopenharmony_ci      if (localeLength >= ULOC_LOCALE_IDENTIFIER_CAPACITY) {
1761cb0ef41Sopenharmony_ci          *status = U_ILLEGAL_ARGUMENT_ERROR;
1771cb0ef41Sopenharmony_ci          return nullptr;
1781cb0ef41Sopenharmony_ci      }
1791cb0ef41Sopenharmony_ci      uprv_strcpy(localeBuf, locale);
1801cb0ef41Sopenharmony_ci      uloc_setKeywordValue("calendar", "gregorian", localeBuf, ULOC_LOCALE_IDENTIFIER_CAPACITY, status);
1811cb0ef41Sopenharmony_ci      if (U_FAILURE(*status)) {
1821cb0ef41Sopenharmony_ci          return nullptr;
1831cb0ef41Sopenharmony_ci      }
1841cb0ef41Sopenharmony_ci      return (UCalendar*)Calendar::createInstance(zone.orphan(), Locale(localeBuf), *status);
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci  return (UCalendar*)Calendar::createInstance(zone.orphan(), Locale(locale), *status);
1871cb0ef41Sopenharmony_ci}
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
1901cb0ef41Sopenharmony_ciucal_close(UCalendar *cal)
1911cb0ef41Sopenharmony_ci{
1921cb0ef41Sopenharmony_ci    if (cal != nullptr) {
1931cb0ef41Sopenharmony_ci        delete (Calendar*) cal;
1941cb0ef41Sopenharmony_ci    }
1951cb0ef41Sopenharmony_ci}
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ciU_CAPI UCalendar* U_EXPORT2
1981cb0ef41Sopenharmony_ciucal_clone(const UCalendar* cal,
1991cb0ef41Sopenharmony_ci           UErrorCode*      status)
2001cb0ef41Sopenharmony_ci{
2011cb0ef41Sopenharmony_ci  if(U_FAILURE(*status)) return 0;
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  Calendar* res = ((Calendar*)cal)->clone();
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  if(res == 0) {
2061cb0ef41Sopenharmony_ci    *status = U_MEMORY_ALLOCATION_ERROR;
2071cb0ef41Sopenharmony_ci    return 0;
2081cb0ef41Sopenharmony_ci  }
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci  return (UCalendar*) res;
2111cb0ef41Sopenharmony_ci}
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
2141cb0ef41Sopenharmony_ciucal_setTimeZone(    UCalendar*      cal,
2151cb0ef41Sopenharmony_ci            const    char16_t*            zoneID,
2161cb0ef41Sopenharmony_ci            int32_t        len,
2171cb0ef41Sopenharmony_ci            UErrorCode *status)
2181cb0ef41Sopenharmony_ci{
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  if(U_FAILURE(*status))
2211cb0ef41Sopenharmony_ci    return;
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  TimeZone* zone = (zoneID==nullptr) ? TimeZone::createDefault()
2241cb0ef41Sopenharmony_ci      : _createTimeZone(zoneID, len, status);
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  if (zone != nullptr) {
2271cb0ef41Sopenharmony_ci      ((Calendar*)cal)->adoptTimeZone(zone);
2281cb0ef41Sopenharmony_ci  }
2291cb0ef41Sopenharmony_ci}
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
2321cb0ef41Sopenharmony_ciucal_getTimeZoneID(const UCalendar *cal,
2331cb0ef41Sopenharmony_ci                   char16_t *result,
2341cb0ef41Sopenharmony_ci                   int32_t resultLength,
2351cb0ef41Sopenharmony_ci                   UErrorCode *status)
2361cb0ef41Sopenharmony_ci{
2371cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
2381cb0ef41Sopenharmony_ci        return 0;
2391cb0ef41Sopenharmony_ci    }
2401cb0ef41Sopenharmony_ci    const TimeZone& tz = ((Calendar*)cal)->getTimeZone();
2411cb0ef41Sopenharmony_ci    UnicodeString id;
2421cb0ef41Sopenharmony_ci    tz.getID(id);
2431cb0ef41Sopenharmony_ci    return id.extract(result, resultLength, *status);
2441cb0ef41Sopenharmony_ci}
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
2471cb0ef41Sopenharmony_ciucal_getTimeZoneDisplayName(const     UCalendar*                 cal,
2481cb0ef41Sopenharmony_ci                    UCalendarDisplayNameType     type,
2491cb0ef41Sopenharmony_ci                    const char             *locale,
2501cb0ef41Sopenharmony_ci                    char16_t*                  result,
2511cb0ef41Sopenharmony_ci                    int32_t                 resultLength,
2521cb0ef41Sopenharmony_ci                    UErrorCode*             status)
2531cb0ef41Sopenharmony_ci{
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)) return -1;
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ci    const TimeZone& tz = ((Calendar*)cal)->getTimeZone();
2581cb0ef41Sopenharmony_ci    UnicodeString id;
2591cb0ef41Sopenharmony_ci    if (!(result == nullptr && resultLength == 0)) {
2601cb0ef41Sopenharmony_ci        // Null destination for pure preflighting: empty dummy string
2611cb0ef41Sopenharmony_ci        // otherwise, alias the destination buffer
2621cb0ef41Sopenharmony_ci        id.setTo(result, 0, resultLength);
2631cb0ef41Sopenharmony_ci    }
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ci    switch(type) {
2661cb0ef41Sopenharmony_ci  case UCAL_STANDARD:
2671cb0ef41Sopenharmony_ci      tz.getDisplayName(false, TimeZone::LONG, Locale(locale), id);
2681cb0ef41Sopenharmony_ci      break;
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci  case UCAL_SHORT_STANDARD:
2711cb0ef41Sopenharmony_ci      tz.getDisplayName(false, TimeZone::SHORT, Locale(locale), id);
2721cb0ef41Sopenharmony_ci      break;
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci  case UCAL_DST:
2751cb0ef41Sopenharmony_ci      tz.getDisplayName(true, TimeZone::LONG, Locale(locale), id);
2761cb0ef41Sopenharmony_ci      break;
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci  case UCAL_SHORT_DST:
2791cb0ef41Sopenharmony_ci      tz.getDisplayName(true, TimeZone::SHORT, Locale(locale), id);
2801cb0ef41Sopenharmony_ci      break;
2811cb0ef41Sopenharmony_ci    }
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci    return id.extract(result, resultLength, *status);
2841cb0ef41Sopenharmony_ci}
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ciU_CAPI UBool  U_EXPORT2
2871cb0ef41Sopenharmony_ciucal_inDaylightTime(    const    UCalendar*      cal,
2881cb0ef41Sopenharmony_ci                    UErrorCode*     status )
2891cb0ef41Sopenharmony_ci{
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)) return (UBool) -1;
2921cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->inDaylightTime(*status);
2931cb0ef41Sopenharmony_ci}
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
2961cb0ef41Sopenharmony_ciucal_setGregorianChange(UCalendar *cal, UDate date, UErrorCode *pErrorCode) {
2971cb0ef41Sopenharmony_ci    if(U_FAILURE(*pErrorCode)) {
2981cb0ef41Sopenharmony_ci        return;
2991cb0ef41Sopenharmony_ci    }
3001cb0ef41Sopenharmony_ci    Calendar *cpp_cal = (Calendar *)cal;
3011cb0ef41Sopenharmony_ci    GregorianCalendar *gregocal = dynamic_cast<GregorianCalendar *>(cpp_cal);
3021cb0ef41Sopenharmony_ci    // Not if(gregocal == nullptr) {
3031cb0ef41Sopenharmony_ci    // because we really want to work only with a GregorianCalendar, not with
3041cb0ef41Sopenharmony_ci    // its subclasses like BuddhistCalendar.
3051cb0ef41Sopenharmony_ci    if (cpp_cal == nullptr) {
3061cb0ef41Sopenharmony_ci        // We normally don't check "this" pointers for nullptr, but this here avoids
3071cb0ef41Sopenharmony_ci        // compiler-generated exception-throwing code in case cal == nullptr.
3081cb0ef41Sopenharmony_ci        *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
3091cb0ef41Sopenharmony_ci        return;
3101cb0ef41Sopenharmony_ci    }
3111cb0ef41Sopenharmony_ci    if(typeid(*cpp_cal) != typeid(GregorianCalendar) &&
3121cb0ef41Sopenharmony_ci       typeid(*cpp_cal) != typeid(ISO8601Calendar)) {
3131cb0ef41Sopenharmony_ci        *pErrorCode = U_UNSUPPORTED_ERROR;
3141cb0ef41Sopenharmony_ci        return;
3151cb0ef41Sopenharmony_ci    }
3161cb0ef41Sopenharmony_ci    gregocal->setGregorianChange(date, *pErrorCode);
3171cb0ef41Sopenharmony_ci}
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ciU_CAPI UDate U_EXPORT2
3201cb0ef41Sopenharmony_ciucal_getGregorianChange(const UCalendar *cal, UErrorCode *pErrorCode) {
3211cb0ef41Sopenharmony_ci    if(U_FAILURE(*pErrorCode)) {
3221cb0ef41Sopenharmony_ci        return (UDate)0;
3231cb0ef41Sopenharmony_ci    }
3241cb0ef41Sopenharmony_ci    const Calendar *cpp_cal = (const Calendar *)cal;
3251cb0ef41Sopenharmony_ci    const GregorianCalendar *gregocal = dynamic_cast<const GregorianCalendar *>(cpp_cal);
3261cb0ef41Sopenharmony_ci    // Not if(gregocal == nullptr) {
3271cb0ef41Sopenharmony_ci    // see comments in ucal_setGregorianChange().
3281cb0ef41Sopenharmony_ci    if (cpp_cal == nullptr) {
3291cb0ef41Sopenharmony_ci        // We normally don't check "this" pointers for nullptr, but this here avoids
3301cb0ef41Sopenharmony_ci        // compiler-generated exception-throwing code in case cal == nullptr.
3311cb0ef41Sopenharmony_ci        *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
3321cb0ef41Sopenharmony_ci        return (UDate)0;
3331cb0ef41Sopenharmony_ci    }
3341cb0ef41Sopenharmony_ci    if(typeid(*cpp_cal) != typeid(GregorianCalendar) &&
3351cb0ef41Sopenharmony_ci       typeid(*cpp_cal) != typeid(ISO8601Calendar)) {
3361cb0ef41Sopenharmony_ci        *pErrorCode = U_UNSUPPORTED_ERROR;
3371cb0ef41Sopenharmony_ci        return (UDate)0;
3381cb0ef41Sopenharmony_ci    }
3391cb0ef41Sopenharmony_ci    return gregocal->getGregorianChange();
3401cb0ef41Sopenharmony_ci}
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
3431cb0ef41Sopenharmony_ciucal_getAttribute(    const    UCalendar*              cal,
3441cb0ef41Sopenharmony_ci                  UCalendarAttribute      attr) UPRV_NO_SANITIZE_UNDEFINED {
3451cb0ef41Sopenharmony_ci    switch(attr) {
3461cb0ef41Sopenharmony_ci  case UCAL_LENIENT:
3471cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->isLenient();
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci  case UCAL_FIRST_DAY_OF_WEEK:
3501cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getFirstDayOfWeek();
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci  case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK:
3531cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getMinimalDaysInFirstWeek();
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ci  case UCAL_REPEATED_WALL_TIME:
3561cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getRepeatedWallTimeOption();
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci  case UCAL_SKIPPED_WALL_TIME:
3591cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getSkippedWallTimeOption();
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci  default:
3621cb0ef41Sopenharmony_ci      break;
3631cb0ef41Sopenharmony_ci    }
3641cb0ef41Sopenharmony_ci    return -1;
3651cb0ef41Sopenharmony_ci}
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
3681cb0ef41Sopenharmony_ciucal_setAttribute(      UCalendar*              cal,
3691cb0ef41Sopenharmony_ci                  UCalendarAttribute      attr,
3701cb0ef41Sopenharmony_ci                  int32_t                 newValue)
3711cb0ef41Sopenharmony_ci{
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci    switch(attr) {
3741cb0ef41Sopenharmony_ci  case UCAL_LENIENT:
3751cb0ef41Sopenharmony_ci      ((Calendar*)cal)->setLenient((UBool)newValue);
3761cb0ef41Sopenharmony_ci      break;
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ci  case UCAL_FIRST_DAY_OF_WEEK:
3791cb0ef41Sopenharmony_ci      ((Calendar*)cal)->setFirstDayOfWeek((UCalendarDaysOfWeek)newValue);
3801cb0ef41Sopenharmony_ci      break;
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci  case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK:
3831cb0ef41Sopenharmony_ci      ((Calendar*)cal)->setMinimalDaysInFirstWeek((uint8_t)newValue);
3841cb0ef41Sopenharmony_ci      break;
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci  case UCAL_REPEATED_WALL_TIME:
3871cb0ef41Sopenharmony_ci      ((Calendar*)cal)->setRepeatedWallTimeOption((UCalendarWallTimeOption)newValue);
3881cb0ef41Sopenharmony_ci      break;
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ci  case UCAL_SKIPPED_WALL_TIME:
3911cb0ef41Sopenharmony_ci      ((Calendar*)cal)->setSkippedWallTimeOption((UCalendarWallTimeOption)newValue);
3921cb0ef41Sopenharmony_ci      break;
3931cb0ef41Sopenharmony_ci    }
3941cb0ef41Sopenharmony_ci}
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ciU_CAPI const char* U_EXPORT2
3971cb0ef41Sopenharmony_ciucal_getAvailable(int32_t index)
3981cb0ef41Sopenharmony_ci{
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ci    return uloc_getAvailable(index);
4011cb0ef41Sopenharmony_ci}
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
4041cb0ef41Sopenharmony_ciucal_countAvailable()
4051cb0ef41Sopenharmony_ci{
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci    return uloc_countAvailable();
4081cb0ef41Sopenharmony_ci}
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ciU_CAPI UDate  U_EXPORT2
4111cb0ef41Sopenharmony_ciucal_getMillis(    const    UCalendar*      cal,
4121cb0ef41Sopenharmony_ci               UErrorCode*     status)
4131cb0ef41Sopenharmony_ci{
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)) return (UDate) 0;
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->getTime(*status);
4181cb0ef41Sopenharmony_ci}
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
4211cb0ef41Sopenharmony_ciucal_setMillis(        UCalendar*      cal,
4221cb0ef41Sopenharmony_ci               UDate           dateTime,
4231cb0ef41Sopenharmony_ci               UErrorCode*     status )
4241cb0ef41Sopenharmony_ci{
4251cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)) return;
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci    ((Calendar*)cal)->setTime(dateTime, *status);
4281cb0ef41Sopenharmony_ci}
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci// TBD: why does this take an UErrorCode?
4311cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
4321cb0ef41Sopenharmony_ciucal_setDate(        UCalendar*        cal,
4331cb0ef41Sopenharmony_ci             int32_t            year,
4341cb0ef41Sopenharmony_ci             int32_t            month,
4351cb0ef41Sopenharmony_ci             int32_t            date,
4361cb0ef41Sopenharmony_ci             UErrorCode        *status)
4371cb0ef41Sopenharmony_ci{
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)) return;
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci    ((Calendar*)cal)->set(year, month, date);
4421cb0ef41Sopenharmony_ci}
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ci// TBD: why does this take an UErrorCode?
4451cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
4461cb0ef41Sopenharmony_ciucal_setDateTime(    UCalendar*        cal,
4471cb0ef41Sopenharmony_ci                 int32_t            year,
4481cb0ef41Sopenharmony_ci                 int32_t            month,
4491cb0ef41Sopenharmony_ci                 int32_t            date,
4501cb0ef41Sopenharmony_ci                 int32_t            hour,
4511cb0ef41Sopenharmony_ci                 int32_t            minute,
4521cb0ef41Sopenharmony_ci                 int32_t            second,
4531cb0ef41Sopenharmony_ci                 UErrorCode        *status)
4541cb0ef41Sopenharmony_ci{
4551cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)) return;
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci    ((Calendar*)cal)->set(year, month, date, hour, minute, second);
4581cb0ef41Sopenharmony_ci}
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ciU_CAPI UBool  U_EXPORT2
4611cb0ef41Sopenharmony_ciucal_equivalentTo(    const UCalendar*      cal1,
4621cb0ef41Sopenharmony_ci                  const UCalendar*      cal2)
4631cb0ef41Sopenharmony_ci{
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci    return ((Calendar*)cal1)->isEquivalentTo(*((Calendar*)cal2));
4661cb0ef41Sopenharmony_ci}
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
4691cb0ef41Sopenharmony_ciucal_add(    UCalendar*                cal,
4701cb0ef41Sopenharmony_ci         UCalendarDateFields        field,
4711cb0ef41Sopenharmony_ci         int32_t                    amount,
4721cb0ef41Sopenharmony_ci         UErrorCode*                status) UPRV_NO_SANITIZE_UNDEFINED {
4731cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)) return;
4741cb0ef41Sopenharmony_ci    if (field < 0 || UCAL_FIELD_COUNT <= field) {
4751cb0ef41Sopenharmony_ci        *status = U_ILLEGAL_ARGUMENT_ERROR;
4761cb0ef41Sopenharmony_ci        return;
4771cb0ef41Sopenharmony_ci    }
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci    ((Calendar*)cal)->add(field, amount, *status);
4801cb0ef41Sopenharmony_ci}
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
4831cb0ef41Sopenharmony_ciucal_roll(        UCalendar*            cal,
4841cb0ef41Sopenharmony_ci          UCalendarDateFields field,
4851cb0ef41Sopenharmony_ci          int32_t                amount,
4861cb0ef41Sopenharmony_ci          UErrorCode*            status) UPRV_NO_SANITIZE_UNDEFINED {
4871cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)) return;
4881cb0ef41Sopenharmony_ci    if (field < 0 || UCAL_FIELD_COUNT <= field) {
4891cb0ef41Sopenharmony_ci        *status = U_ILLEGAL_ARGUMENT_ERROR;
4901cb0ef41Sopenharmony_ci        return;
4911cb0ef41Sopenharmony_ci    }
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci    ((Calendar*)cal)->roll(field, amount, *status);
4941cb0ef41Sopenharmony_ci}
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ciU_CAPI int32_t  U_EXPORT2
4971cb0ef41Sopenharmony_ciucal_get(    const    UCalendar*                cal,
4981cb0ef41Sopenharmony_ci         UCalendarDateFields        field,
4991cb0ef41Sopenharmony_ci         UErrorCode*                status ) UPRV_NO_SANITIZE_UNDEFINED {
5001cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)) return -1;
5011cb0ef41Sopenharmony_ci    if (field < 0 || UCAL_FIELD_COUNT <= field) {
5021cb0ef41Sopenharmony_ci        *status = U_ILLEGAL_ARGUMENT_ERROR;
5031cb0ef41Sopenharmony_ci        return -1;
5041cb0ef41Sopenharmony_ci    }
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->get(field, *status);
5071cb0ef41Sopenharmony_ci}
5081cb0ef41Sopenharmony_ci
5091cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
5101cb0ef41Sopenharmony_ciucal_set(    UCalendar*                cal,
5111cb0ef41Sopenharmony_ci         UCalendarDateFields        field,
5121cb0ef41Sopenharmony_ci         int32_t                    value) UPRV_NO_SANITIZE_UNDEFINED {
5131cb0ef41Sopenharmony_ci    if (field < 0 || UCAL_FIELD_COUNT <= field) {
5141cb0ef41Sopenharmony_ci        return;
5151cb0ef41Sopenharmony_ci    }
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_ci    ((Calendar*)cal)->set(field, value);
5181cb0ef41Sopenharmony_ci}
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_ciU_CAPI UBool  U_EXPORT2
5211cb0ef41Sopenharmony_ciucal_isSet(    const    UCalendar*                cal,
5221cb0ef41Sopenharmony_ci           UCalendarDateFields        field) UPRV_NO_SANITIZE_UNDEFINED {
5231cb0ef41Sopenharmony_ci    if (field < 0 || UCAL_FIELD_COUNT <= field) {
5241cb0ef41Sopenharmony_ci        return false;
5251cb0ef41Sopenharmony_ci    }
5261cb0ef41Sopenharmony_ci
5271cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->isSet(field);
5281cb0ef41Sopenharmony_ci}
5291cb0ef41Sopenharmony_ci
5301cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
5311cb0ef41Sopenharmony_ciucal_clearField(    UCalendar*            cal,
5321cb0ef41Sopenharmony_ci                UCalendarDateFields field) UPRV_NO_SANITIZE_UNDEFINED {
5331cb0ef41Sopenharmony_ci    if (field < 0 || UCAL_FIELD_COUNT <= field) {
5341cb0ef41Sopenharmony_ci        return;
5351cb0ef41Sopenharmony_ci    }
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_ci    ((Calendar*)cal)->clear(field);
5381cb0ef41Sopenharmony_ci}
5391cb0ef41Sopenharmony_ci
5401cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
5411cb0ef41Sopenharmony_ciucal_clear(UCalendar* calendar)
5421cb0ef41Sopenharmony_ci{
5431cb0ef41Sopenharmony_ci
5441cb0ef41Sopenharmony_ci    ((Calendar*)calendar)->clear();
5451cb0ef41Sopenharmony_ci}
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_ciU_CAPI int32_t  U_EXPORT2
5481cb0ef41Sopenharmony_ciucal_getLimit(    const    UCalendar*              cal,
5491cb0ef41Sopenharmony_ci              UCalendarDateFields     field,
5501cb0ef41Sopenharmony_ci              UCalendarLimitType      type,
5511cb0ef41Sopenharmony_ci              UErrorCode        *status) UPRV_NO_SANITIZE_UNDEFINED {
5521cb0ef41Sopenharmony_ci    if(status==0 || U_FAILURE(*status)) {
5531cb0ef41Sopenharmony_ci        return -1;
5541cb0ef41Sopenharmony_ci    }
5551cb0ef41Sopenharmony_ci    if (field < 0 || UCAL_FIELD_COUNT <= field) {
5561cb0ef41Sopenharmony_ci        *status = U_ILLEGAL_ARGUMENT_ERROR;
5571cb0ef41Sopenharmony_ci        return -1;
5581cb0ef41Sopenharmony_ci    }
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_ci    switch(type) {
5611cb0ef41Sopenharmony_ci  case UCAL_MINIMUM:
5621cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getMinimum(field);
5631cb0ef41Sopenharmony_ci
5641cb0ef41Sopenharmony_ci  case UCAL_MAXIMUM:
5651cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getMaximum(field);
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ci  case UCAL_GREATEST_MINIMUM:
5681cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getGreatestMinimum(field);
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci  case UCAL_LEAST_MAXIMUM:
5711cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getLeastMaximum(field);
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_ci  case UCAL_ACTUAL_MINIMUM:
5741cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getActualMinimum(field,
5751cb0ef41Sopenharmony_ci          *status);
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_ci  case UCAL_ACTUAL_MAXIMUM:
5781cb0ef41Sopenharmony_ci      return ((Calendar*)cal)->getActualMaximum(field,
5791cb0ef41Sopenharmony_ci          *status);
5801cb0ef41Sopenharmony_ci
5811cb0ef41Sopenharmony_ci  default:
5821cb0ef41Sopenharmony_ci      break;
5831cb0ef41Sopenharmony_ci    }
5841cb0ef41Sopenharmony_ci    return -1;
5851cb0ef41Sopenharmony_ci}
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_ciU_CAPI const char * U_EXPORT2
5881cb0ef41Sopenharmony_ciucal_getLocaleByType(const UCalendar *cal, ULocDataLocaleType type, UErrorCode* status)
5891cb0ef41Sopenharmony_ci{
5901cb0ef41Sopenharmony_ci    if (cal == nullptr) {
5911cb0ef41Sopenharmony_ci        if (U_SUCCESS(*status)) {
5921cb0ef41Sopenharmony_ci            *status = U_ILLEGAL_ARGUMENT_ERROR;
5931cb0ef41Sopenharmony_ci        }
5941cb0ef41Sopenharmony_ci        return nullptr;
5951cb0ef41Sopenharmony_ci    }
5961cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->getLocaleID(type, *status);
5971cb0ef41Sopenharmony_ci}
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ciU_CAPI const char * U_EXPORT2
6001cb0ef41Sopenharmony_ciucal_getTZDataVersion(UErrorCode* status)
6011cb0ef41Sopenharmony_ci{
6021cb0ef41Sopenharmony_ci    return TimeZone::getTZDataVersion(*status);
6031cb0ef41Sopenharmony_ci}
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
6061cb0ef41Sopenharmony_ciucal_getCanonicalTimeZoneID(const char16_t* id, int32_t len,
6071cb0ef41Sopenharmony_ci                            char16_t* result, int32_t resultCapacity, UBool *isSystemID, UErrorCode* status) {
6081cb0ef41Sopenharmony_ci    if(status == 0 || U_FAILURE(*status)) {
6091cb0ef41Sopenharmony_ci        return 0;
6101cb0ef41Sopenharmony_ci    }
6111cb0ef41Sopenharmony_ci    if (isSystemID) {
6121cb0ef41Sopenharmony_ci        *isSystemID = false;
6131cb0ef41Sopenharmony_ci    }
6141cb0ef41Sopenharmony_ci    if (id == 0 || len == 0 || result == 0 || resultCapacity <= 0) {
6151cb0ef41Sopenharmony_ci        *status = U_ILLEGAL_ARGUMENT_ERROR;
6161cb0ef41Sopenharmony_ci        return 0;
6171cb0ef41Sopenharmony_ci    }
6181cb0ef41Sopenharmony_ci    int32_t reslen = 0;
6191cb0ef41Sopenharmony_ci    UnicodeString canonical;
6201cb0ef41Sopenharmony_ci    UBool systemID = false;
6211cb0ef41Sopenharmony_ci    TimeZone::getCanonicalID(UnicodeString(id, len), canonical, systemID, *status);
6221cb0ef41Sopenharmony_ci    if (U_SUCCESS(*status)) {
6231cb0ef41Sopenharmony_ci        if (isSystemID) {
6241cb0ef41Sopenharmony_ci            *isSystemID = systemID;
6251cb0ef41Sopenharmony_ci        }
6261cb0ef41Sopenharmony_ci        reslen = canonical.extract(result, resultCapacity, *status);
6271cb0ef41Sopenharmony_ci    }
6281cb0ef41Sopenharmony_ci    return reslen;
6291cb0ef41Sopenharmony_ci}
6301cb0ef41Sopenharmony_ci
6311cb0ef41Sopenharmony_ciU_DRAFT int32_t U_EXPORT2
6321cb0ef41Sopenharmony_ciucal_getIanaTimeZoneID(const char16_t* id, int32_t len,
6331cb0ef41Sopenharmony_ci                        char16_t* result, int32_t resultCapacity, UErrorCode* status)
6341cb0ef41Sopenharmony_ci{
6351cb0ef41Sopenharmony_ci    UnicodeString ianaID;
6361cb0ef41Sopenharmony_ci    TimeZone::getIanaID(UnicodeString(id, len), ianaID, *status);
6371cb0ef41Sopenharmony_ci    return ianaID.extract(result, resultCapacity, *status);
6381cb0ef41Sopenharmony_ci}
6391cb0ef41Sopenharmony_ci
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ciU_CAPI const char * U_EXPORT2
6421cb0ef41Sopenharmony_ciucal_getType(const UCalendar *cal, UErrorCode* status)
6431cb0ef41Sopenharmony_ci{
6441cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
6451cb0ef41Sopenharmony_ci        return nullptr;
6461cb0ef41Sopenharmony_ci    }
6471cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->getType();
6481cb0ef41Sopenharmony_ci}
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_ciU_CAPI UCalendarWeekdayType U_EXPORT2
6511cb0ef41Sopenharmony_ciucal_getDayOfWeekType(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode* status)
6521cb0ef41Sopenharmony_ci{
6531cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
6541cb0ef41Sopenharmony_ci        return UCAL_WEEKDAY;
6551cb0ef41Sopenharmony_ci    }
6561cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->getDayOfWeekType(dayOfWeek, *status);
6571cb0ef41Sopenharmony_ci}
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
6601cb0ef41Sopenharmony_ciucal_getWeekendTransition(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode *status)
6611cb0ef41Sopenharmony_ci{
6621cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
6631cb0ef41Sopenharmony_ci        return 0;
6641cb0ef41Sopenharmony_ci    }
6651cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->getWeekendTransition(dayOfWeek, *status);
6661cb0ef41Sopenharmony_ci}
6671cb0ef41Sopenharmony_ci
6681cb0ef41Sopenharmony_ciU_CAPI UBool U_EXPORT2
6691cb0ef41Sopenharmony_ciucal_isWeekend(const UCalendar *cal, UDate date, UErrorCode *status)
6701cb0ef41Sopenharmony_ci{
6711cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
6721cb0ef41Sopenharmony_ci        return false;
6731cb0ef41Sopenharmony_ci    }
6741cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->isWeekend(date, *status);
6751cb0ef41Sopenharmony_ci}
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_ciU_CAPI int32_t  U_EXPORT2
6781cb0ef41Sopenharmony_ciucal_getFieldDifference(UCalendar* cal, UDate target,
6791cb0ef41Sopenharmony_ci                        UCalendarDateFields field,
6801cb0ef41Sopenharmony_ci                        UErrorCode* status )
6811cb0ef41Sopenharmony_ci{
6821cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
6831cb0ef41Sopenharmony_ci        return 0;
6841cb0ef41Sopenharmony_ci    }
6851cb0ef41Sopenharmony_ci    return ((Calendar*)cal)->fieldDifference(target, field, *status);
6861cb0ef41Sopenharmony_ci}
6871cb0ef41Sopenharmony_ci
6881cb0ef41Sopenharmony_ci
6891cb0ef41Sopenharmony_cistatic const UEnumeration defaultKeywordValues = {
6901cb0ef41Sopenharmony_ci    nullptr,
6911cb0ef41Sopenharmony_ci    nullptr,
6921cb0ef41Sopenharmony_ci    ulist_close_keyword_values_iterator,
6931cb0ef41Sopenharmony_ci    ulist_count_keyword_values,
6941cb0ef41Sopenharmony_ci    uenum_unextDefault,
6951cb0ef41Sopenharmony_ci    ulist_next_keyword_value,
6961cb0ef41Sopenharmony_ci    ulist_reset_keyword_values_iterator
6971cb0ef41Sopenharmony_ci};
6981cb0ef41Sopenharmony_ci
6991cb0ef41Sopenharmony_cistatic const char * const CAL_TYPES[] = {
7001cb0ef41Sopenharmony_ci        "gregorian",
7011cb0ef41Sopenharmony_ci        "japanese",
7021cb0ef41Sopenharmony_ci        "buddhist",
7031cb0ef41Sopenharmony_ci        "roc",
7041cb0ef41Sopenharmony_ci        "persian",
7051cb0ef41Sopenharmony_ci        "islamic-civil",
7061cb0ef41Sopenharmony_ci        "islamic",
7071cb0ef41Sopenharmony_ci        "hebrew",
7081cb0ef41Sopenharmony_ci        "chinese",
7091cb0ef41Sopenharmony_ci        "indian",
7101cb0ef41Sopenharmony_ci        "coptic",
7111cb0ef41Sopenharmony_ci        "ethiopic",
7121cb0ef41Sopenharmony_ci        "ethiopic-amete-alem",
7131cb0ef41Sopenharmony_ci        "iso8601",
7141cb0ef41Sopenharmony_ci        "dangi",
7151cb0ef41Sopenharmony_ci        "islamic-umalqura",
7161cb0ef41Sopenharmony_ci        "islamic-tbla",
7171cb0ef41Sopenharmony_ci        "islamic-rgsa",
7181cb0ef41Sopenharmony_ci        nullptr
7191cb0ef41Sopenharmony_ci};
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ciU_CAPI UEnumeration* U_EXPORT2
7221cb0ef41Sopenharmony_ciucal_getKeywordValuesForLocale(const char * /* key */, const char* locale, UBool commonlyUsed, UErrorCode *status) {
7231cb0ef41Sopenharmony_ci    // Resolve region
7241cb0ef41Sopenharmony_ci    char prefRegion[ULOC_COUNTRY_CAPACITY];
7251cb0ef41Sopenharmony_ci    (void)ulocimp_getRegionForSupplementalData(locale, true, prefRegion, sizeof(prefRegion), status);
7261cb0ef41Sopenharmony_ci
7271cb0ef41Sopenharmony_ci    // Read preferred calendar values from supplementalData calendarPreference
7281cb0ef41Sopenharmony_ci    UResourceBundle *rb = ures_openDirect(nullptr, "supplementalData", status);
7291cb0ef41Sopenharmony_ci    ures_getByKey(rb, "calendarPreferenceData", rb, status);
7301cb0ef41Sopenharmony_ci    UResourceBundle *order = ures_getByKey(rb, prefRegion, nullptr, status);
7311cb0ef41Sopenharmony_ci    if (*status == U_MISSING_RESOURCE_ERROR && rb != nullptr) {
7321cb0ef41Sopenharmony_ci        *status = U_ZERO_ERROR;
7331cb0ef41Sopenharmony_ci        order = ures_getByKey(rb, "001", nullptr, status);
7341cb0ef41Sopenharmony_ci    }
7351cb0ef41Sopenharmony_ci
7361cb0ef41Sopenharmony_ci    // Create a list of calendar type strings
7371cb0ef41Sopenharmony_ci    UList *values = nullptr;
7381cb0ef41Sopenharmony_ci    if (U_SUCCESS(*status)) {
7391cb0ef41Sopenharmony_ci        values = ulist_createEmptyList(status);
7401cb0ef41Sopenharmony_ci        if (U_SUCCESS(*status)) {
7411cb0ef41Sopenharmony_ci            for (int i = 0; i < ures_getSize(order); i++) {
7421cb0ef41Sopenharmony_ci                int32_t len;
7431cb0ef41Sopenharmony_ci                const char16_t *type = ures_getStringByIndex(order, i, &len, status);
7441cb0ef41Sopenharmony_ci                char *caltype = (char*)uprv_malloc(len + 1);
7451cb0ef41Sopenharmony_ci                if (caltype == nullptr) {
7461cb0ef41Sopenharmony_ci                    *status = U_MEMORY_ALLOCATION_ERROR;
7471cb0ef41Sopenharmony_ci                    break;
7481cb0ef41Sopenharmony_ci                }
7491cb0ef41Sopenharmony_ci                u_UCharsToChars(type, caltype, len);
7501cb0ef41Sopenharmony_ci                *(caltype + len) = 0;
7511cb0ef41Sopenharmony_ci
7521cb0ef41Sopenharmony_ci                ulist_addItemEndList(values, caltype, true, status);
7531cb0ef41Sopenharmony_ci                if (U_FAILURE(*status)) {
7541cb0ef41Sopenharmony_ci                    break;
7551cb0ef41Sopenharmony_ci                }
7561cb0ef41Sopenharmony_ci            }
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_ci            if (U_SUCCESS(*status) && !commonlyUsed) {
7591cb0ef41Sopenharmony_ci                // If not commonlyUsed, add other available values
7601cb0ef41Sopenharmony_ci                for (int32_t i = 0; CAL_TYPES[i] != nullptr; i++) {
7611cb0ef41Sopenharmony_ci                    if (!ulist_containsString(values, CAL_TYPES[i], (int32_t)uprv_strlen(CAL_TYPES[i]))) {
7621cb0ef41Sopenharmony_ci                        ulist_addItemEndList(values, CAL_TYPES[i], false, status);
7631cb0ef41Sopenharmony_ci                        if (U_FAILURE(*status)) {
7641cb0ef41Sopenharmony_ci                            break;
7651cb0ef41Sopenharmony_ci                        }
7661cb0ef41Sopenharmony_ci                    }
7671cb0ef41Sopenharmony_ci                }
7681cb0ef41Sopenharmony_ci            }
7691cb0ef41Sopenharmony_ci            if (U_FAILURE(*status)) {
7701cb0ef41Sopenharmony_ci                ulist_deleteList(values);
7711cb0ef41Sopenharmony_ci                values = nullptr;
7721cb0ef41Sopenharmony_ci            }
7731cb0ef41Sopenharmony_ci        }
7741cb0ef41Sopenharmony_ci    }
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci    ures_close(order);
7771cb0ef41Sopenharmony_ci    ures_close(rb);
7781cb0ef41Sopenharmony_ci
7791cb0ef41Sopenharmony_ci    if (U_FAILURE(*status) || values == nullptr) {
7801cb0ef41Sopenharmony_ci        return nullptr;
7811cb0ef41Sopenharmony_ci    }
7821cb0ef41Sopenharmony_ci
7831cb0ef41Sopenharmony_ci    // Create string enumeration
7841cb0ef41Sopenharmony_ci    UEnumeration *en = (UEnumeration*)uprv_malloc(sizeof(UEnumeration));
7851cb0ef41Sopenharmony_ci    if (en == nullptr) {
7861cb0ef41Sopenharmony_ci        *status = U_MEMORY_ALLOCATION_ERROR;
7871cb0ef41Sopenharmony_ci        ulist_deleteList(values);
7881cb0ef41Sopenharmony_ci        return nullptr;
7891cb0ef41Sopenharmony_ci    }
7901cb0ef41Sopenharmony_ci    ulist_resetList(values);
7911cb0ef41Sopenharmony_ci    memcpy(en, &defaultKeywordValues, sizeof(UEnumeration));
7921cb0ef41Sopenharmony_ci    en->context = values;
7931cb0ef41Sopenharmony_ci    return en;
7941cb0ef41Sopenharmony_ci}
7951cb0ef41Sopenharmony_ci
7961cb0ef41Sopenharmony_ciU_CAPI UBool U_EXPORT2
7971cb0ef41Sopenharmony_ciucal_getTimeZoneTransitionDate(const UCalendar* cal, UTimeZoneTransitionType type,
7981cb0ef41Sopenharmony_ci                               UDate* transition, UErrorCode* status)
7991cb0ef41Sopenharmony_ci{
8001cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
8011cb0ef41Sopenharmony_ci        return false;
8021cb0ef41Sopenharmony_ci    }
8031cb0ef41Sopenharmony_ci    UDate base = ((Calendar*)cal)->getTime(*status);
8041cb0ef41Sopenharmony_ci    const TimeZone& tz = ((Calendar*)cal)->getTimeZone();
8051cb0ef41Sopenharmony_ci    const BasicTimeZone * btz = dynamic_cast<const BasicTimeZone *>(&tz);
8061cb0ef41Sopenharmony_ci    if (btz != nullptr && U_SUCCESS(*status)) {
8071cb0ef41Sopenharmony_ci        TimeZoneTransition tzt;
8081cb0ef41Sopenharmony_ci        UBool inclusive = (type == UCAL_TZ_TRANSITION_NEXT_INCLUSIVE || type == UCAL_TZ_TRANSITION_PREVIOUS_INCLUSIVE);
8091cb0ef41Sopenharmony_ci        UBool result = (type == UCAL_TZ_TRANSITION_NEXT || type == UCAL_TZ_TRANSITION_NEXT_INCLUSIVE)?
8101cb0ef41Sopenharmony_ci                        btz->getNextTransition(base, inclusive, tzt):
8111cb0ef41Sopenharmony_ci                        btz->getPreviousTransition(base, inclusive, tzt);
8121cb0ef41Sopenharmony_ci        if (result) {
8131cb0ef41Sopenharmony_ci            *transition = tzt.getTime();
8141cb0ef41Sopenharmony_ci            return true;
8151cb0ef41Sopenharmony_ci        }
8161cb0ef41Sopenharmony_ci    }
8171cb0ef41Sopenharmony_ci    return false;
8181cb0ef41Sopenharmony_ci}
8191cb0ef41Sopenharmony_ci
8201cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
8211cb0ef41Sopenharmony_ciucal_getWindowsTimeZoneID(const char16_t* id, int32_t len, char16_t* winid, int32_t winidCapacity, UErrorCode* status) {
8221cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
8231cb0ef41Sopenharmony_ci        return 0;
8241cb0ef41Sopenharmony_ci    }
8251cb0ef41Sopenharmony_ci
8261cb0ef41Sopenharmony_ci    int32_t resultLen = 0;
8271cb0ef41Sopenharmony_ci    UnicodeString resultWinID;
8281cb0ef41Sopenharmony_ci
8291cb0ef41Sopenharmony_ci    TimeZone::getWindowsID(UnicodeString(id, len), resultWinID, *status);
8301cb0ef41Sopenharmony_ci    if (U_SUCCESS(*status) && resultWinID.length() > 0) {
8311cb0ef41Sopenharmony_ci        resultLen = resultWinID.length();
8321cb0ef41Sopenharmony_ci        resultWinID.extract(winid, winidCapacity, *status);
8331cb0ef41Sopenharmony_ci    }
8341cb0ef41Sopenharmony_ci
8351cb0ef41Sopenharmony_ci    return resultLen;
8361cb0ef41Sopenharmony_ci}
8371cb0ef41Sopenharmony_ci
8381cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
8391cb0ef41Sopenharmony_ciucal_getTimeZoneIDForWindowsID(const char16_t* winid, int32_t len, const char* region, char16_t* id, int32_t idCapacity, UErrorCode* status) {
8401cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
8411cb0ef41Sopenharmony_ci        return 0;
8421cb0ef41Sopenharmony_ci    }
8431cb0ef41Sopenharmony_ci
8441cb0ef41Sopenharmony_ci    int32_t resultLen = 0;
8451cb0ef41Sopenharmony_ci    UnicodeString resultID;
8461cb0ef41Sopenharmony_ci
8471cb0ef41Sopenharmony_ci    TimeZone::getIDForWindowsID(UnicodeString(winid, len), region, resultID, *status);
8481cb0ef41Sopenharmony_ci    if (U_SUCCESS(*status) && resultID.length() > 0) {
8491cb0ef41Sopenharmony_ci        resultLen = resultID.length();
8501cb0ef41Sopenharmony_ci        resultID.extract(id, idCapacity, *status);
8511cb0ef41Sopenharmony_ci    }
8521cb0ef41Sopenharmony_ci
8531cb0ef41Sopenharmony_ci    return resultLen;
8541cb0ef41Sopenharmony_ci}
8551cb0ef41Sopenharmony_ci
8561cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2 ucal_getTimeZoneOffsetFromLocal(
8571cb0ef41Sopenharmony_ci    const UCalendar* cal,
8581cb0ef41Sopenharmony_ci    UTimeZoneLocalOption nonExistingTimeOpt,
8591cb0ef41Sopenharmony_ci    UTimeZoneLocalOption duplicatedTimeOpt,
8601cb0ef41Sopenharmony_ci    int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status)
8611cb0ef41Sopenharmony_ci{
8621cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
8631cb0ef41Sopenharmony_ci        return;
8641cb0ef41Sopenharmony_ci    }
8651cb0ef41Sopenharmony_ci    UDate date = ((Calendar*)cal)->getTime(*status);
8661cb0ef41Sopenharmony_ci    if (U_FAILURE(*status)) {
8671cb0ef41Sopenharmony_ci        return;
8681cb0ef41Sopenharmony_ci    }
8691cb0ef41Sopenharmony_ci    const TimeZone& tz = ((Calendar*)cal)->getTimeZone();
8701cb0ef41Sopenharmony_ci    const BasicTimeZone* btz = dynamic_cast<const BasicTimeZone *>(&tz);
8711cb0ef41Sopenharmony_ci    if (btz == nullptr) {
8721cb0ef41Sopenharmony_ci        *status = U_ILLEGAL_ARGUMENT_ERROR;
8731cb0ef41Sopenharmony_ci        return;
8741cb0ef41Sopenharmony_ci    }
8751cb0ef41Sopenharmony_ci    btz->getOffsetFromLocal(
8761cb0ef41Sopenharmony_ci        date, nonExistingTimeOpt, duplicatedTimeOpt,
8771cb0ef41Sopenharmony_ci        *rawOffset, *dstOffset, *status);
8781cb0ef41Sopenharmony_ci}
8791cb0ef41Sopenharmony_ci
8801cb0ef41Sopenharmony_ci#endif /* #if !UCONFIG_NO_FORMATTING */
881