tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ICU4XChineseBasedCalendar.cpp (8029B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "mozilla/intl/calendar/ICU4XChineseBasedCalendar.h"
      6 
      7 #include "mozilla/Assertions.h"
      8 
      9 namespace mozilla::intl::calendar {
     10 
     11 ICU4XChineseBasedCalendar::ICU4XChineseBasedCalendar(
     12    icu4x::capi::CalendarKind kind, const icu::Locale& locale,
     13    UErrorCode& success)
     14    : ICU4XCalendar(kind, locale, success) {}
     15 
     16 ICU4XChineseBasedCalendar::ICU4XChineseBasedCalendar(
     17    icu4x::capi::CalendarKind kind, const icu::TimeZone& timeZone,
     18    const icu::Locale& locale, UErrorCode& success)
     19    : ICU4XCalendar(kind, timeZone, locale, success) {}
     20 
     21 ICU4XChineseBasedCalendar::ICU4XChineseBasedCalendar(
     22    const ICU4XChineseBasedCalendar& other)
     23    : ICU4XCalendar(other) {}
     24 
     25 ICU4XChineseBasedCalendar::~ICU4XChineseBasedCalendar() = default;
     26 
     27 ////////////////////////////////////////////
     28 // ICU4XCalendar implementation overrides //
     29 ////////////////////////////////////////////
     30 
     31 bool ICU4XChineseBasedCalendar::hasLeapMonths() const { return true; }
     32 
     33 bool ICU4XChineseBasedCalendar::hasMonthCode(MonthCode monthCode) const {
     34  return monthCode.ordinal() <= 12;
     35 }
     36 
     37 bool ICU4XChineseBasedCalendar::requiresFallbackForExtendedYear(
     38    int32_t year) const {
     39  // Same limits as in js/src/builtin/temporal/Calendar.cpp.
     40  return std::abs(year) > 10'000;
     41 }
     42 
     43 bool ICU4XChineseBasedCalendar::requiresFallbackForGregorianYear(
     44    int32_t year) const {
     45  // Same limits as in js/src/builtin/temporal/Calendar.cpp.
     46  return std::abs(year) > 10'000;
     47 }
     48 
     49 ////////////////////////////////////////////
     50 // icu::Calendar implementation overrides //
     51 ////////////////////////////////////////////
     52 
     53 bool ICU4XChineseBasedCalendar::inTemporalLeapYear(UErrorCode& status) const {
     54  int32_t days = getActualMaximum(UCAL_DAY_OF_YEAR, status);
     55  if (U_FAILURE(status)) {
     56    return false;
     57  }
     58 
     59  constexpr int32_t maxDaysInMonth = 30;
     60  constexpr int32_t monthsInNonLeapYear = 12;
     61  return days > (monthsInNonLeapYear * maxDaysInMonth);
     62 }
     63 
     64 void ICU4XChineseBasedCalendar::handleComputeFields(int32_t julianDay,
     65                                                    UErrorCode& status) {
     66  int32_t gyear = getGregorianYear();
     67 
     68  // Use the fallback calendar for years outside the range supported by ICU4X.
     69  if (requiresFallbackForGregorianYear(gyear)) {
     70    handleComputeFieldsFromFallback(julianDay, status);
     71    return;
     72  }
     73 
     74  int32_t gmonth = getGregorianMonth() + 1;
     75  int32_t gday = getGregorianDayOfMonth();
     76 
     77  MOZ_ASSERT(1 <= gmonth && gmonth <= 12);
     78  MOZ_ASSERT(1 <= gday && gday <= 31);
     79 
     80  auto date = createICU4XDate(ISODate{gyear, gmonth, gday}, status);
     81  if (U_FAILURE(status)) {
     82    return;
     83  }
     84  MOZ_ASSERT(date);
     85 
     86  MonthCode monthCode = monthCodeFrom(date.get());
     87  int32_t extendedYear =
     88      icu4x::capi::icu4x_Date_era_year_or_related_iso_mv1(date.get());
     89  int32_t month = icu4x::capi::icu4x_Date_ordinal_month_mv1(date.get());
     90  int32_t dayOfMonth = icu4x::capi::icu4x_Date_day_of_month_mv1(date.get());
     91  int32_t dayOfYear = icu4x::capi::icu4x_Date_day_of_year_mv1(date.get());
     92 
     93  MOZ_ASSERT(1 <= month && month <= 13);
     94  MOZ_ASSERT(1 <= dayOfMonth && dayOfMonth <= 30);
     95  MOZ_ASSERT(1 <= dayOfYear && dayOfYear <= (13 * 30));
     96 
     97  // Difference between the Chinese calendar era (the extended year 1) and the
     98  // start year used for cycle computations. This is the sixtieth year of reign
     99  // of Huáng Dì. Other sources use the first year of reign, which means using
    100  // -2697 instead. Both numbers result in the same year of cycle, but the
    101  // latter number gives a different cycle number. To align with the ICU4C
    102  // Chinese calendar implementation, we use -2637 here.
    103  constexpr int32_t chineseCalendarYearDiff = -2637;
    104 
    105  // Compute the cycle and year of cycle relative to the Chinese calendar, even
    106  // when this is the Dangi calendar.
    107  int32_t chineseCalendarYear = extendedYear - chineseCalendarYearDiff;
    108  int32_t cycle_year = chineseCalendarYear - 1;
    109  int32_t cycle = FloorDiv(cycle_year, 60);
    110  int32_t yearOfCycle = cycle_year - (cycle * 60);
    111 
    112  internalSet(UCAL_ERA, cycle + 1);
    113  internalSet(UCAL_YEAR, yearOfCycle + 1);
    114  internalSet(UCAL_EXTENDED_YEAR, extendedYear);
    115  internalSet(UCAL_MONTH, monthCode.ordinal() - 1);
    116  internalSet(UCAL_ORDINAL_MONTH, month - 1);
    117  internalSet(UCAL_IS_LEAP_MONTH, monthCode.isLeapMonth() ? 1 : 0);
    118  internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
    119  internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
    120 }
    121 
    122 // Limits table copied from i18n/chnsecal.cpp. Licensed under:
    123 //
    124 // © 2016 and later: Unicode, Inc. and others.
    125 // License & terms of use: http://www.unicode.org/copyright.html
    126 static const int32_t CHINESE_CALENDAR_LIMITS[UCAL_FIELD_COUNT][4] = {
    127    // clang-format off
    128    // Minimum  Greatest     Least    Maximum
    129    //           Minimum   Maximum
    130    {        1,        1,    83333,    83333}, // ERA
    131    {        1,        1,       60,       60}, // YEAR
    132    {        0,        0,       11,       11}, // MONTH
    133    {        1,        1,       50,       55}, // WEEK_OF_YEAR
    134    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // WEEK_OF_MONTH
    135    {        1,        1,       29,       30}, // DAY_OF_MONTH
    136    {        1,        1,      353,      385}, // DAY_OF_YEAR
    137    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK
    138    {       -1,       -1,        5,        5}, // DAY_OF_WEEK_IN_MONTH
    139    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // AM_PM
    140    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR
    141    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY
    142    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE
    143    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND
    144    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND
    145    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET
    146    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET
    147    { -5000000, -5000000,  5000000,  5000000}, // YEAR_WOY
    148    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL
    149    { -5000000, -5000000,  5000000,  5000000}, // EXTENDED_YEAR
    150    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY
    151    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY
    152    {        0,        0,        1,        1}, // IS_LEAP_MONTH
    153    {        0,        0,       11,       12}, // ORDINAL_MONTH
    154    // clang-format on
    155 };
    156 
    157 int32_t ICU4XChineseBasedCalendar::handleGetLimit(UCalendarDateFields field,
    158                                                  ELimitType limitType) const {
    159  return CHINESE_CALENDAR_LIMITS[field][limitType];
    160 }
    161 
    162 // Field resolution table copied from i18n/chnsecal.cpp. Licensed under:
    163 //
    164 // © 2016 and later: Unicode, Inc. and others.
    165 // License & terms of use: http://www.unicode.org/copyright.html
    166 const icu::UFieldResolutionTable
    167    ICU4XChineseBasedCalendar::CHINESE_DATE_PRECEDENCE[] = {
    168        // clang-format off
    169  {
    170    { UCAL_DAY_OF_MONTH, kResolveSTOP },
    171    { UCAL_WEEK_OF_YEAR, UCAL_DAY_OF_WEEK, kResolveSTOP },
    172    { UCAL_WEEK_OF_MONTH, UCAL_DAY_OF_WEEK, kResolveSTOP },
    173    { UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DAY_OF_WEEK, kResolveSTOP },
    174    { UCAL_WEEK_OF_YEAR, UCAL_DOW_LOCAL, kResolveSTOP },
    175    { UCAL_WEEK_OF_MONTH, UCAL_DOW_LOCAL, kResolveSTOP },
    176    { UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DOW_LOCAL, kResolveSTOP },
    177    { UCAL_DAY_OF_YEAR, kResolveSTOP },
    178    { kResolveRemap | UCAL_DAY_OF_MONTH, UCAL_IS_LEAP_MONTH, kResolveSTOP },
    179    { kResolveSTOP }
    180  },
    181  {
    182    { UCAL_WEEK_OF_YEAR, kResolveSTOP },
    183    { UCAL_WEEK_OF_MONTH, kResolveSTOP },
    184    { UCAL_DAY_OF_WEEK_IN_MONTH, kResolveSTOP },
    185    { kResolveRemap | UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DAY_OF_WEEK, kResolveSTOP },
    186    { kResolveRemap | UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DOW_LOCAL, kResolveSTOP },
    187    { kResolveSTOP }
    188  },
    189  {{kResolveSTOP}}
    190        // clang-format on
    191 };
    192 
    193 const icu::UFieldResolutionTable*
    194 ICU4XChineseBasedCalendar::getFieldResolutionTable() const {
    195  return CHINESE_DATE_PRECEDENCE;
    196 }
    197 
    198 }  // namespace mozilla::intl::calendar