Bug 1728180 - Part 2: Call mozilla::intl::Calendar methods in intl_GetCalendarInfo. r=platform-i18n-reviewers,dminor

Use `mozilla::intl::Calendar` instead of directly calling ICU in
`intl_GetCalendarInfo`. This implies that the days of the week are now ordered
the same way as in the "Intl Locale Info API" and the "Temporal" proposal, i.e.
starting from Monday=1 to Sunday=7.

Differential Revision: https://phabricator.services.mozilla.com/D126228
This commit is contained in:
André Bargull 2021-09-23 07:43:51 +00:00
parent aae4fba66e
commit a3e91cb71a
6 changed files with 49 additions and 69 deletions

View File

@ -141,16 +141,16 @@ mozIntl.getCalendarInfo(locale)
The API will return the following calendar information for a given locale code:
* firstDayOfWeek
an integer in the range 1=Sunday to 7=Saturday indicating the day
considered the first day of the week in calendars, e.g. 1 for en-US,
2 for en-GB, 1 for bn-IN
an integer in the range 1=Monday to 7=Sunday indicating the day
considered the first day of the week in calendars, e.g. 7 for en-US,
1 for en-GB, 7 for bn-IN
* minDays
an integer in the range of 1 to 7 indicating the minimum number
of days required in the first week of the year, e.g. 1 for en-US, 4 for de
* weekend
an array with values in the range 1=Sunday to 7=Saturday indicating the days
of the week considered as part of the weekend, e.g. [1, 7] for en-US and en-GB,
[1] for bn-IN (note that "weekend" is *not* necessarily two days)
an array with values in the range 1=Monday to 7=Sunday indicating the days
of the week considered as part of the weekend, e.g. [6, 7] for en-US and en-GB,
[7] for bn-IN (note that "weekend" is *not* necessarily two days)
Those bits of information should be especially useful for any UI that works
with calendar data.
@ -162,9 +162,9 @@ Example:
// omitting the `locale` argument will make the API return data for the
// current Gecko application UI locale.
let {
firstDayOfWeek, // 2
firstDayOfWeek, // 1
minDays, // 4
weekend, // [1, 7]
weekend, // [6, 7]
calendar, // "gregory"
locale, // "pl"
} = Services.intl.getCalendarInfo();

View File

@ -31,7 +31,6 @@
#include "builtin/intl/NumberingSystemsGenerated.h"
#include "builtin/intl/PluralRules.h"
#include "builtin/intl/RelativeTimeFormat.h"
#include "builtin/intl/ScopedICUObject.h"
#include "builtin/intl/SharedIntlData.h"
#include "ds/Sort.h"
#include "js/CharacterEncoding.h"
@ -42,8 +41,6 @@
#include "js/PropertySpec.h"
#include "js/Result.h"
#include "js/StableStringChars.h"
#include "unicode/ucal.h"
#include "unicode/utypes.h"
#include "vm/GlobalObject.h"
#include "vm/JSAtom.h"
#include "vm/JSContext.h"
@ -68,16 +65,12 @@ bool js::intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
UErrorCode status = U_ZERO_ERROR;
const UChar* uTimeZone = nullptr;
int32_t uTimeZoneLength = 0;
UCalendar* cal = ucal_open(uTimeZone, uTimeZoneLength, locale.get(),
UCAL_DEFAULT, &status);
if (U_FAILURE(status)) {
intl::ReportInternalError(cx);
auto result = mozilla::intl::Calendar::TryCreate(locale.get());
if (result.isErr()) {
intl::ReportInternalError(cx, result.unwrapErr());
return false;
}
ScopedICUObject<UCalendar, ucal_close> toClose(cal);
auto calendar = result.unwrap();
RootedObject info(cx, NewPlainObject(cx));
if (!info) {
@ -85,15 +78,13 @@ bool js::intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp) {
}
RootedValue v(cx);
int32_t firstDayOfWeek = ucal_getAttribute(cal, UCAL_FIRST_DAY_OF_WEEK);
v.setInt32(firstDayOfWeek);
v.setInt32(static_cast<int32_t>(calendar->GetFirstDayOfWeek()));
if (!DefineDataProperty(cx, info, cx->names().firstDayOfWeek, v)) {
return false;
}
int32_t minDays = ucal_getAttribute(cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK);
v.setInt32(minDays);
v.setInt32(calendar->GetMinimalDaysInFirstWeek());
if (!DefineDataProperty(cx, info, cx->names().minDays, v)) {
return false;
}
@ -103,31 +94,16 @@ bool js::intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
for (int i = UCAL_SUNDAY; i <= UCAL_SATURDAY; i++) {
UCalendarDaysOfWeek dayOfWeek = static_cast<UCalendarDaysOfWeek>(i);
UCalendarWeekdayType type = ucal_getDayOfWeekType(cal, dayOfWeek, &status);
if (U_FAILURE(status)) {
intl::ReportInternalError(cx);
return false;
}
auto weekend = calendar->GetWeekend();
if (weekend.isErr()) {
intl::ReportInternalError(cx, weekend.unwrapErr());
return false;
}
switch (type) {
case UCAL_WEEKDAY:
break;
case UCAL_WEEKEND:
if (!NewbornArrayPush(cx, weekendArray, Int32Value(i))) {
return false;
}
break;
case UCAL_WEEKEND_ONSET:
case UCAL_WEEKEND_CEASE:
// At the time this code was added, ICU apparently never behaves this
// way, so just throw, so that users will report a bug and we can
// decide what to do.
intl::ReportInternalError(cx);
return false;
default:
break;
for (auto day : weekend.unwrap()) {
if (!NewbornArrayPush(cx, weekendArray,
Int32Value(static_cast<int32_t>(day)))) {
return false;
}
}

View File

@ -20,17 +20,17 @@ extern const JSClass IntlClass;
* properties:
*
* firstDayOfWeek
* an integer in the range 1=Sunday to 7=Saturday indicating the day
* considered the first day of the week in calendars, e.g. 1 for en-US,
* 2 for en-GB, 1 for bn-IN
* an integer in the range 1=Monday to 7=Sunday indicating the day
* considered the first day of the week in calendars, e.g. 7 for en-US,
* 1 for en-GB, 7 for bn-IN
* minDays
* an integer in the range of 1 to 7 indicating the minimum number
* of days required in the first week of the year, e.g. 1 for en-US,
* 4 for de
* weekend
* an array with values in the range 1=Sunday to 7=Saturday indicating the
* days of the week considered as part of the weekend, e.g. [1, 7] for en-US
* and en-GB, [1] for bn-IN (note that "weekend" is *not* necessarily two
* an array with values in the range 1=Monday to 7=Sunday indicating the
* days of the week considered as part of the weekend, e.g. [6, 7] for en-US
* and en-GB, [7] for bn-IN (note that "weekend" is *not* necessarily two
* days)
*
* NOTE: "calendar" and "locale" properties are *not* added to the object.

View File

@ -43,7 +43,7 @@ function Intl_supportedValuesOf(key) {
* weekend:
* The days of the week considered as the weekend for the resolved locale.
*
* Days are encoded as integers in the range 1=Sunday to 7=Saturday.
* Days are encoded as integers in the range 1=Monday to 7=Sunday.
*/
function Intl_getCalendarInfo(locales) {
// 1. Let requestLocales be ? CanonicalizeLocaleList(locales).

View File

@ -23,51 +23,51 @@ let gCI = Intl.getCalendarInfo;
assertEq(gCI.length, 1);
checkCalendarInfo(gCI('en-US'), {
firstDayOfWeek: 1,
firstDayOfWeek: 7,
minDays: 1,
weekend: [1, 7],
weekend: [6, 7],
calendar: "gregory",
locale: "en-US"
});
checkCalendarInfo(gCI('en-IL'), {
firstDayOfWeek: 1,
firstDayOfWeek: 7,
minDays: 1,
weekend: [6, 7],
weekend: [5, 6],
calendar: "gregory",
locale: "en-IL"
});
checkCalendarInfo(gCI('en-GB'), {
firstDayOfWeek: 2,
firstDayOfWeek: 1,
minDays: 4,
weekend: [1, 7],
weekend: [6, 7],
calendar: "gregory",
locale: "en-GB"
});
checkCalendarInfo(gCI('pl'), {
firstDayOfWeek: 2,
firstDayOfWeek: 1,
minDays: 4,
weekend: [1, 7],
weekend: [6, 7],
calendar: "gregory",
locale: "pl"
});
checkCalendarInfo(gCI('ar-IQ'), {
firstDayOfWeek: 7,
firstDayOfWeek: 6,
minDays: 1,
weekend: [6, 7],
weekend: [5, 6],
calendar: "gregory",
locale: "ar-IQ"
});
checkCalendarInfo(gCI('fa-IR'), {
firstDayOfWeek: 7,
firstDayOfWeek: 6,
minDays: 1,
weekend: [6],
weekend: [5],
calendar: "persian",
locale: "fa-IR"
});

View File

@ -271,13 +271,17 @@ var DateTimePickerPanel = class {
getCalendarInfo(locale) {
const calendarInfo = Services.intl.getCalendarInfo(locale);
// Day of week from calendarInfo starts from 1 as Sunday to 7 as Saturday,
// Day of week from calendarInfo starts from 1 as Monday to 7 as Sunday,
// so they need to be mapped to JavaScript convention with 0 as Sunday
// and 6 as Saturday
let firstDayOfWeek = calendarInfo.firstDayOfWeek - 1,
function toDateWeekday(day) {
return day === 7 ? 0 : day;
}
let firstDayOfWeek = toDateWeekday(calendarInfo.firstDayOfWeek),
weekend = calendarInfo.weekend;
let weekends = weekend.map(day => day - 1);
let weekends = weekend.map(toDateWeekday);
return {
firstDayOfWeek,