tor-browser

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

ICU4XCalendar.h (5084B)


      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 #ifndef intl_components_calendar_ICU4XCalendar_h_
      5 #define intl_components_calendar_ICU4XCalendar_h_
      6 
      7 #include "mozilla/intl/calendar/ICU4XUniquePtr.h"
      8 #include "mozilla/intl/calendar/ISODate.h"
      9 #include "mozilla/intl/calendar/MonthCode.h"
     10 
     11 #include <memory>
     12 #include <mutex>
     13 #include <stdint.h>
     14 #include <string_view>
     15 
     16 #include "unicode/calendar.h"
     17 #include "unicode/locid.h"
     18 #include "unicode/timezone.h"
     19 #include "unicode/utypes.h"
     20 
     21 #include "icu4x/CalendarKind.hpp"
     22 
     23 namespace mozilla::intl::calendar {
     24 
     25 /**
     26 * Abstract class to implement icu::Calendar using ICU4X.
     27 */
     28 class ICU4XCalendar : public icu::Calendar {
     29  mutable UniqueICU4XCalendar calendar_{};
     30  mutable std::unique_ptr<icu::Calendar> fallback_{};
     31  icu4x::capi::CalendarKind kind_;
     32 
     33 protected:
     34  ICU4XCalendar(icu4x::capi::CalendarKind kind, const icu::Locale& locale,
     35                UErrorCode& success);
     36  ICU4XCalendar(icu4x::capi::CalendarKind kind, const icu::TimeZone& timeZone,
     37                const icu::Locale& locale, UErrorCode& success);
     38  ICU4XCalendar(const ICU4XCalendar& other);
     39 
     40  /**
     41   * Get or create the underlying ICU4X calendar.
     42   */
     43  icu4x::capi::Calendar* getICU4XCalendar(UErrorCode& status) const;
     44 
     45  /**
     46   * Get or create the ICU4C fallback calendar implementation.
     47   */
     48  icu::Calendar* getFallbackCalendar(UErrorCode& status) const;
     49 
     50 protected:
     51  /**
     52   * Return the ICU4X era name for the given extended year.
     53   */
     54  virtual std::string_view eraName(int32_t extendedYear) const = 0;
     55 
     56  /**
     57   * Return true if this calendar contains any leap months.
     58   */
     59  virtual bool hasLeapMonths() const = 0;
     60 
     61  /**
     62   * Return true if this calendar contains the requested month code.
     63   */
     64  virtual bool hasMonthCode(MonthCode monthCode) const = 0;
     65 
     66  /**
     67   * Subclasses can request to use the ICU4C fallback calendar.
     68   *
     69   * Can be removed when <https://github.com/unicode-org/icu4x/issues/4917> is
     70   * fixed.
     71   */
     72  virtual bool requiresFallbackForExtendedYear(int32_t year) const = 0;
     73  virtual bool requiresFallbackForGregorianYear(int32_t year) const = 0;
     74 
     75 protected:
     76  static constexpr int32_t kEpochStartAsJulianDay =
     77      2440588;  // January 1, 1970 (Gregorian)
     78 
     79  /**
     80   * Return the month code of |date|.
     81   */
     82  static MonthCode monthCodeFrom(const icu4x::capi::Date* date);
     83 
     84  /**
     85   * Create a new ICU4X date object from an ISO date.
     86   */
     87  UniqueICU4XDate createICU4XDate(const ISODate& date,
     88                                  UErrorCode& status) const;
     89 
     90 public:
     91  ICU4XCalendar() = delete;
     92  virtual ~ICU4XCalendar();
     93 
     94  const char* getTemporalMonthCode(UErrorCode& status) const override;
     95  void setTemporalMonthCode(const char* code, UErrorCode& status) override;
     96 
     97  void add(UCalendarDateFields field, int32_t amount,
     98           UErrorCode& status) override;
     99  void add(EDateFields field, int32_t amount, UErrorCode& status) override;
    100  void roll(UCalendarDateFields field, int32_t amount,
    101            UErrorCode& status) override;
    102  void roll(EDateFields field, int32_t amount, UErrorCode& status) override;
    103 
    104 protected:
    105  int32_t internalGetMonth(int32_t defaultValue,
    106                           UErrorCode& status) const override;
    107  int32_t internalGetMonth(UErrorCode& status) const override;
    108 
    109  int64_t handleComputeMonthStart(int32_t extendedYear, int32_t month,
    110                                  UBool useMonth,
    111                                  UErrorCode& status) const override;
    112  int32_t handleGetMonthLength(int32_t extendedYear, int32_t month,
    113                               UErrorCode& status) const override;
    114  int32_t handleGetYearLength(int32_t extendedYear,
    115                              UErrorCode& status) const override;
    116 
    117  int32_t handleGetExtendedYear(UErrorCode& status) override;
    118 
    119 protected:
    120  /**
    121   * handleComputeFields implementation using the ICU4C fallback calendar.
    122   */
    123  void handleComputeFieldsFromFallback(int32_t julianDay, UErrorCode& status);
    124 };
    125 
    126 /**
    127 * `IMPL_SYSTEM_DEFAULT_CENTURY` is internal to "i18n/gregoimp.h", so we have
    128 * to provider our own helper class to implement default centuries.
    129 */
    130 template <class Calendar, class Locale>
    131 class SystemDefaultCentury {
    132  mutable UDate start_ = DBL_MIN;
    133  mutable int32_t startYear_ = -1;
    134  mutable std::once_flag init_{};
    135 
    136  void initialize() const {
    137    UErrorCode status = U_ZERO_ERROR;
    138    Calendar calendar(Locale::identifier, status);
    139    if (U_FAILURE(status)) {
    140      return;
    141    }
    142    calendar.setTime(icu::Calendar::getNow(), status);
    143    calendar.add(UCAL_EXTENDED_YEAR, -80, status);
    144    start_ = calendar.getTime(status);
    145    startYear_ = calendar.get(UCAL_YEAR, status);
    146  }
    147 
    148 public:
    149  UDate start() const {
    150    std::call_once(init_, [this] { initialize(); });
    151    return start_;
    152  }
    153  int32_t startYear() const {
    154    std::call_once(init_, [this] { initialize(); });
    155    return startYear_;
    156  }
    157 };
    158 
    159 }  // namespace mozilla::intl::calendar
    160 
    161 #endif