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/. */
5 #include "mozilla/intl/Calendar.h"
7 #include "unicode/ucal.h"
8 #include "unicode/uloc.h"
9 #include "unicode/utypes.h"
11 namespace mozilla::intl
{
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();
25 ucal_open(zoneID
, zoneIDLen
, aLocale
, UCAL_DEFAULT
, &status
);
27 if (U_FAILURE(status
)) {
28 return Err(ToICUError(status
));
31 return MakeUnique
<Calendar
>(calendar
);
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
));
40 const char* bcp47Type
= uloc_toUnicodeLocaleType("calendar", oldType
);
43 return Err(ICUError::InternalError
);
46 return MakeStringSpan(bcp47Type
);
49 static Weekday
WeekdayFromDaysOfWeek(UCalendarDaysOfWeek weekday
) {
52 return Weekday::Monday
;
54 return Weekday::Tuesday
;
56 return Weekday::Wednesday
;
58 return Weekday::Thursday
;
60 return Weekday::Friday
;
62 return Weekday::Saturday
;
64 return Weekday::Sunday
;
66 MOZ_CRASH("unexpected weekday value");
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);
73 UErrorCode status
= U_ZERO_ERROR
;
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
));
84 case UCAL_WEEKEND_ONSET
:
85 // Treat days which start as a weekday as weekdays.
90 case UCAL_WEEKEND_CEASE
:
91 // Treat days which start as a weekend day as weekend days.
94 weekend
+= WeekdayFromDaysOfWeek(dayOfWeek
);
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
);
106 return WeekdayFromDaysOfWeek(
107 static_cast<UCalendarDaysOfWeek
>(firstDayOfWeek
));
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);
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
));
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
);
134 if (U_SUCCESS(status
)) {
135 return SpanEnumeration
<char>(enumeration
);
138 return Err(ToICUError(status
));
142 SpanResult
<char> Calendar::LegacyIdentifierToBcp47(const char* aIdentifier
,
144 if (aIdentifier
== nullptr) {
145 return Err(InternalError
{});
147 // aLength is not needed here, as the ICU call uses the null terminated
149 return MakeStringSpan(uloc_toUnicodeLocaleType("ca", aIdentifier
));
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
);
160 if (U_SUCCESS(status
)) {
161 return Bcp47IdentifierEnumeration(enumeration
);
164 return Err(ToICUError(status
));
167 Calendar::~Calendar() {
168 MOZ_ASSERT(mCalendar
);
169 ucal_close(mCalendar
);
172 } // namespace mozilla::intl