tor-browser

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

Calendar.cpp (4917B)


      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.h"
      6 
      7 #include "unicode/ucal.h"
      8 #include "unicode/uloc.h"
      9 #include "unicode/utypes.h"
     10 
     11 namespace mozilla::intl {
     12 
     13 /* static */
     14 Result<UniquePtr<Calendar>, ICUError> Calendar::TryCreate(
     15    const char* aLocale, Maybe<Span<const char16_t>> aTimeZoneOverride) {
     16  UErrorCode status = U_ZERO_ERROR;
     17  const UChar* zoneID = nullptr;
     18  int32_t zoneIDLen = 0;
     19  if (aTimeZoneOverride) {
     20    zoneIDLen = static_cast<int32_t>(aTimeZoneOverride->Length());
     21    zoneID = aTimeZoneOverride->Elements();
     22  }
     23 
     24  UCalendar* calendar =
     25      ucal_open(zoneID, zoneIDLen, aLocale, UCAL_DEFAULT, &status);
     26 
     27  if (U_FAILURE(status)) {
     28    return Err(ToICUError(status));
     29  }
     30 
     31  return MakeUnique<Calendar>(calendar);
     32 }
     33 
     34 Result<Span<const char>, ICUError> Calendar::GetBcp47Type() {
     35  UErrorCode status = U_ZERO_ERROR;
     36  const char* oldType = ucal_getType(mCalendar, &status);
     37  if (U_FAILURE(status)) {
     38    return Err(ToICUError(status));
     39  }
     40  const char* bcp47Type = uloc_toUnicodeLocaleType("calendar", oldType);
     41 
     42  if (!bcp47Type) {
     43    return Err(ICUError::InternalError);
     44  }
     45 
     46  return MakeStringSpan(bcp47Type);
     47 }
     48 
     49 static Weekday WeekdayFromDaysOfWeek(UCalendarDaysOfWeek weekday) {
     50  switch (weekday) {
     51    case UCAL_MONDAY:
     52      return Weekday::Monday;
     53    case UCAL_TUESDAY:
     54      return Weekday::Tuesday;
     55    case UCAL_WEDNESDAY:
     56      return Weekday::Wednesday;
     57    case UCAL_THURSDAY:
     58      return Weekday::Thursday;
     59    case UCAL_FRIDAY:
     60      return Weekday::Friday;
     61    case UCAL_SATURDAY:
     62      return Weekday::Saturday;
     63    case UCAL_SUNDAY:
     64      return Weekday::Sunday;
     65  }
     66  MOZ_CRASH("unexpected weekday value");
     67 }
     68 
     69 Result<EnumSet<Weekday>, ICUError> Calendar::GetWeekend() {
     70  static_assert(static_cast<int32_t>(UCAL_SUNDAY) == 1);
     71  static_assert(static_cast<int32_t>(UCAL_SATURDAY) == 7);
     72 
     73  UErrorCode status = U_ZERO_ERROR;
     74 
     75  EnumSet<Weekday> weekend;
     76  for (int32_t i = UCAL_SUNDAY; i <= UCAL_SATURDAY; i++) {
     77    auto dayOfWeek = static_cast<UCalendarDaysOfWeek>(i);
     78    auto type = ucal_getDayOfWeekType(mCalendar, dayOfWeek, &status);
     79    if (U_FAILURE(status)) {
     80      return Err(ToICUError(status));
     81    }
     82 
     83    switch (type) {
     84      case UCAL_WEEKEND_ONSET:
     85        // Treat days which start as a weekday as weekdays.
     86        [[fallthrough]];
     87      case UCAL_WEEKDAY:
     88        break;
     89 
     90      case UCAL_WEEKEND_CEASE:
     91        // Treat days which start as a weekend day as weekend days.
     92        [[fallthrough]];
     93      case UCAL_WEEKEND:
     94        weekend += WeekdayFromDaysOfWeek(dayOfWeek);
     95        break;
     96    }
     97  }
     98 
     99  return weekend;
    100 }
    101 
    102 Weekday Calendar::GetFirstDayOfWeek() {
    103  int32_t firstDayOfWeek = ucal_getAttribute(mCalendar, UCAL_FIRST_DAY_OF_WEEK);
    104  MOZ_ASSERT(UCAL_SUNDAY <= firstDayOfWeek && firstDayOfWeek <= UCAL_SATURDAY);
    105 
    106  return WeekdayFromDaysOfWeek(
    107      static_cast<UCalendarDaysOfWeek>(firstDayOfWeek));
    108 }
    109 
    110 int32_t Calendar::GetMinimalDaysInFirstWeek() {
    111  int32_t minimalDays =
    112      ucal_getAttribute(mCalendar, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK);
    113  MOZ_ASSERT(1 <= minimalDays && minimalDays <= 7);
    114 
    115  return minimalDays;
    116 }
    117 
    118 Result<Ok, ICUError> Calendar::SetTimeInMs(double aUnixEpoch) {
    119  UErrorCode status = U_ZERO_ERROR;
    120  ucal_setMillis(mCalendar, aUnixEpoch, &status);
    121  if (U_FAILURE(status)) {
    122    return Err(ToICUError(status));
    123  }
    124  return Ok{};
    125 }
    126 
    127 /* static */
    128 Result<SpanEnumeration<char>, ICUError>
    129 Calendar::GetLegacyKeywordValuesForLocale(const char* aLocale) {
    130  UErrorCode status = U_ZERO_ERROR;
    131  UEnumeration* enumeration = ucal_getKeywordValuesForLocale(
    132      "calendar", aLocale, /* commonlyUsed */ false, &status);
    133 
    134  if (U_SUCCESS(status)) {
    135    return SpanEnumeration<char>(enumeration);
    136  }
    137 
    138  return Err(ToICUError(status));
    139 }
    140 
    141 /* static */
    142 SpanResult<char> Calendar::LegacyIdentifierToBcp47(const char* aIdentifier,
    143                                                   int32_t aLength) {
    144  if (aIdentifier == nullptr) {
    145    return Err(InternalError{});
    146  }
    147  // aLength is not needed here, as the ICU call uses the null terminated
    148  // string.
    149  return MakeStringSpan(uloc_toUnicodeLocaleType("ca", aIdentifier));
    150 }
    151 
    152 /* static */
    153 Result<Calendar::Bcp47IdentifierEnumeration, ICUError>
    154 Calendar::GetBcp47KeywordValuesForLocale(const char* aLocale,
    155                                         CommonlyUsed aCommonlyUsed) {
    156  UErrorCode status = U_ZERO_ERROR;
    157  UEnumeration* enumeration = ucal_getKeywordValuesForLocale(
    158      "calendar", aLocale, static_cast<bool>(aCommonlyUsed), &status);
    159 
    160  if (U_SUCCESS(status)) {
    161    return Bcp47IdentifierEnumeration(enumeration);
    162  }
    163 
    164  return Err(ToICUError(status));
    165 }
    166 
    167 Calendar::~Calendar() {
    168  MOZ_ASSERT(mCalendar);
    169  ucal_close(mCalendar);
    170 }
    171 
    172 }  // namespace mozilla::intl