diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /intl/components/src/Calendar.cpp | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'intl/components/src/Calendar.cpp')
-rw-r--r-- | intl/components/src/Calendar.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/intl/components/src/Calendar.cpp b/intl/components/src/Calendar.cpp new file mode 100644 index 0000000000..d44dedaaae --- /dev/null +++ b/intl/components/src/Calendar.cpp @@ -0,0 +1,172 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/intl/Calendar.h" + +#include "unicode/ucal.h" +#include "unicode/uloc.h" +#include "unicode/utypes.h" + +namespace mozilla::intl { + +/* static */ +Result<UniquePtr<Calendar>, ICUError> Calendar::TryCreate( + const char* aLocale, Maybe<Span<const char16_t>> aTimeZoneOverride) { + UErrorCode status = U_ZERO_ERROR; + const UChar* zoneID = nullptr; + int32_t zoneIDLen = 0; + if (aTimeZoneOverride) { + zoneIDLen = static_cast<int32_t>(aTimeZoneOverride->Length()); + zoneID = aTimeZoneOverride->Elements(); + } + + UCalendar* calendar = + ucal_open(zoneID, zoneIDLen, aLocale, UCAL_DEFAULT, &status); + + if (U_FAILURE(status)) { + return Err(ToICUError(status)); + } + + return MakeUnique<Calendar>(calendar); +} + +Result<Span<const char>, ICUError> Calendar::GetBcp47Type() { + UErrorCode status = U_ZERO_ERROR; + const char* oldType = ucal_getType(mCalendar, &status); + if (U_FAILURE(status)) { + return Err(ToICUError(status)); + } + const char* bcp47Type = uloc_toUnicodeLocaleType("calendar", oldType); + + if (!bcp47Type) { + return Err(ICUError::InternalError); + } + + return MakeStringSpan(bcp47Type); +} + +static Weekday WeekdayFromDaysOfWeek(UCalendarDaysOfWeek weekday) { + switch (weekday) { + case UCAL_MONDAY: + return Weekday::Monday; + case UCAL_TUESDAY: + return Weekday::Tuesday; + case UCAL_WEDNESDAY: + return Weekday::Wednesday; + case UCAL_THURSDAY: + return Weekday::Thursday; + case UCAL_FRIDAY: + return Weekday::Friday; + case UCAL_SATURDAY: + return Weekday::Saturday; + case UCAL_SUNDAY: + return Weekday::Sunday; + } + MOZ_CRASH("unexpected weekday value"); +} + +Result<EnumSet<Weekday>, ICUError> Calendar::GetWeekend() { + static_assert(static_cast<int32_t>(UCAL_SUNDAY) == 1); + static_assert(static_cast<int32_t>(UCAL_SATURDAY) == 7); + + UErrorCode status = U_ZERO_ERROR; + + EnumSet<Weekday> weekend; + for (int32_t i = UCAL_SUNDAY; i <= UCAL_SATURDAY; i++) { + auto dayOfWeek = static_cast<UCalendarDaysOfWeek>(i); + auto type = ucal_getDayOfWeekType(mCalendar, dayOfWeek, &status); + if (U_FAILURE(status)) { + return Err(ToICUError(status)); + } + + switch (type) { + case UCAL_WEEKEND_ONSET: + // Treat days which start as a weekday as weekdays. + [[fallthrough]]; + case UCAL_WEEKDAY: + break; + + case UCAL_WEEKEND_CEASE: + // Treat days which start as a weekend day as weekend days. + [[fallthrough]]; + case UCAL_WEEKEND: + weekend += WeekdayFromDaysOfWeek(dayOfWeek); + break; + } + } + + return weekend; +} + +Weekday Calendar::GetFirstDayOfWeek() { + int32_t firstDayOfWeek = ucal_getAttribute(mCalendar, UCAL_FIRST_DAY_OF_WEEK); + MOZ_ASSERT(UCAL_SUNDAY <= firstDayOfWeek && firstDayOfWeek <= UCAL_SATURDAY); + + return WeekdayFromDaysOfWeek( + static_cast<UCalendarDaysOfWeek>(firstDayOfWeek)); +} + +int32_t Calendar::GetMinimalDaysInFirstWeek() { + int32_t minimalDays = + ucal_getAttribute(mCalendar, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK); + MOZ_ASSERT(1 <= minimalDays && minimalDays <= 7); + + return minimalDays; +} + +Result<Ok, ICUError> Calendar::SetTimeInMs(double aUnixEpoch) { + UErrorCode status = U_ZERO_ERROR; + ucal_setMillis(mCalendar, aUnixEpoch, &status); + if (U_FAILURE(status)) { + return Err(ToICUError(status)); + } + return Ok{}; +} + +/* static */ +Result<SpanEnumeration<char>, ICUError> +Calendar::GetLegacyKeywordValuesForLocale(const char* aLocale) { + UErrorCode status = U_ZERO_ERROR; + UEnumeration* enumeration = ucal_getKeywordValuesForLocale( + "calendar", aLocale, /* commonlyUsed */ false, &status); + + if (U_SUCCESS(status)) { + return SpanEnumeration<char>(enumeration); + } + + return Err(ToICUError(status)); +} + +/* static */ +SpanResult<char> Calendar::LegacyIdentifierToBcp47(const char* aIdentifier, + int32_t aLength) { + if (aIdentifier == nullptr) { + return Err(InternalError{}); + } + // aLength is not needed here, as the ICU call uses the null terminated + // string. + return MakeStringSpan(uloc_toUnicodeLocaleType("ca", aIdentifier)); +} + +/* static */ +Result<Calendar::Bcp47IdentifierEnumeration, ICUError> +Calendar::GetBcp47KeywordValuesForLocale(const char* aLocale, + CommonlyUsed aCommonlyUsed) { + UErrorCode status = U_ZERO_ERROR; + UEnumeration* enumeration = ucal_getKeywordValuesForLocale( + "calendar", aLocale, static_cast<bool>(aCommonlyUsed), &status); + + if (U_SUCCESS(status)) { + return Bcp47IdentifierEnumeration(enumeration); + } + + return Err(ToICUError(status)); +} + +Calendar::~Calendar() { + MOZ_ASSERT(mCalendar); + ucal_close(mCalendar); +} + +} // namespace mozilla::intl |