feat(localize): add reusable generators for month and weekday names

This commit is contained in:
Mikhail Bashkirov 2019-05-13 10:29:57 +02:00
parent 97fe0f0aa7
commit 043106c1cf
5 changed files with 166 additions and 0 deletions

View file

@ -1,5 +1,7 @@
export { formatDate } from './src/date/formatDate.js';
export { getDateFormatBasedOnLocale } from './src/date/getDateFormatBasedOnLocale.js';
export { getMonthNames } from './src/date/getMonthNames.js';
export { getWeekdayNames } from './src/date/getWeekdayNames.js';
export { parseDate } from './src/date/parseDate.js';
export {
formatNumber,

View file

@ -0,0 +1,25 @@
import { normalizeDate } from './normalizeDate.js';
const monthsLocaleCache = {};
export function getMonthNames({ locale }) {
let months = monthsLocaleCache[locale];
if (months) {
return months;
}
months = [];
const formatter = new Intl.DateTimeFormat(locale, { month: 'long' });
for (let i = 0; i < 12; i += 1) {
const date = new Date(2019, i, 1);
const formattedDate = formatter.format(date);
const normalizedDate = normalizeDate(formattedDate);
months.push(normalizedDate);
}
monthsLocaleCache[locale] = months;
return months;
}

View file

@ -0,0 +1,53 @@
import { normalizeDate } from './normalizeDate.js';
const weekdayNamesCache = {};
/**
* @desc Return cached weekday names for locale for all styles ('long', 'short', 'narrow')
* @param {string} locale locale
* @returns {Object} like { long: ['Sunday', 'Monday'...], short: ['Sun', ...], narrow: ['S', ...] }
*/
function getCachedWeekdayNames(locale) {
let weekdays = weekdayNamesCache[locale];
if (weekdays) {
return weekdays;
}
weekdayNamesCache[locale] = { long: [], short: [], narrow: [] };
['long', 'short', 'narrow'].forEach(style => {
weekdays = weekdayNamesCache[locale][style];
const formatter = new Intl.DateTimeFormat(locale, { weekday: style });
const date = new Date('2019/04/07'); // start from Sunday
for (let i = 0; i < 7; i += 1) {
const weekday = formatter.format(date);
const normalizedWeekday = normalizeDate(weekday);
weekdays.push(normalizedWeekday);
date.setDate(date.getDate() + 1);
}
});
return weekdayNamesCache[locale];
}
// TODO: consider using a database with information for the `firstDayOfWeek`?
// https://github.com/unicode-cldr/cldr-core/blob/35.0.0/supplemental/weekData.json#L60
// https://github.com/tc39/ecma402/issues/6#issuecomment-114079502
/**
* @desc Returns weekday names for locale
* @param {string} options.locale locale
* @param {string} [options.style=long] long, short or narrow
* @param {number} [options.firstDayOfWeek=0] 0 (Sunday), 1 (Monday), etc...
* @returns {Array} like: ['Sunday', 'Monday', 'Tuesday', ...etc].
*/
export function getWeekdayNames({ locale, style = 'long', firstDayOfWeek = 0 } = {}) {
const weekdays = getCachedWeekdayNames(locale)[style];
const orderedWeekdays = [];
for (let i = firstDayOfWeek; i < firstDayOfWeek + 7; i += 1) {
orderedWeekdays.push(weekdays[i % 7]);
}
return orderedWeekdays;
}

View file

@ -0,0 +1,21 @@
import { expect } from '@open-wc/testing';
import { getMonthNames } from '../../src/date/getMonthNames.js';
function s(strings) {
return strings[0].split(' ');
}
describe('getMonthNames', () => {
it('generates month names for a given locale', () => {
expect(getMonthNames({ locale: 'en-GB' })).to.deep.equal(
s`January February March April May June July August September October November December`,
);
expect(getMonthNames({ locale: 'nl-NL' })).to.deep.equal(
s`januari februari maart april mei juni juli augustus september oktober november december`,
);
expect(getMonthNames({ locale: 'zh-CH' })).to.deep.equal(
s`一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月`,
);
});
});

View file

@ -0,0 +1,65 @@
import { expect } from '@open-wc/testing';
import { getWeekdayNames } from '../../src/date/getWeekdayNames.js';
function s(strings) {
return strings[0].split(' ');
}
describe('getWeekdayNames', () => {
it('generates weekday names for a given locale with defaults (from Sunday, long style)', () => {
expect(getWeekdayNames({ locale: 'en-GB' })).to.deep.equal(
s`Sunday Monday Tuesday Wednesday Thursday Friday Saturday`,
);
expect(getWeekdayNames({ locale: 'nl-NL' })).to.deep.equal(
s`zondag maandag dinsdag woensdag donderdag vrijdag zaterdag`,
);
expect(getWeekdayNames({ locale: 'zh-CH' })).to.deep.equal(
s`星期日 星期一 星期二 星期三 星期四 星期五 星期六`,
);
});
it('allows to specify a day when a week starts', () => {
expect(getWeekdayNames({ locale: 'en-GB', firstDayOfWeek: 7 })).to.deep.equal(
s`Sunday Monday Tuesday Wednesday Thursday Friday Saturday`,
);
expect(getWeekdayNames({ locale: 'en-GB', firstDayOfWeek: 1 })).to.deep.equal(
s`Monday Tuesday Wednesday Thursday Friday Saturday Sunday`,
);
expect(getWeekdayNames({ locale: 'en-GB', firstDayOfWeek: 2 })).to.deep.equal(
s`Tuesday Wednesday Thursday Friday Saturday Sunday Monday`,
);
expect(getWeekdayNames({ locale: 'en-GB', firstDayOfWeek: 3 })).to.deep.equal(
s`Wednesday Thursday Friday Saturday Sunday Monday Tuesday`,
);
expect(getWeekdayNames({ locale: 'en-GB', firstDayOfWeek: 4 })).to.deep.equal(
s`Thursday Friday Saturday Sunday Monday Tuesday Wednesday`,
);
expect(getWeekdayNames({ locale: 'en-GB', firstDayOfWeek: 5 })).to.deep.equal(
s`Friday Saturday Sunday Monday Tuesday Wednesday Thursday`,
);
expect(getWeekdayNames({ locale: 'en-GB', firstDayOfWeek: 6 })).to.deep.equal(
s`Saturday Sunday Monday Tuesday Wednesday Thursday Friday`,
);
});
it('supports "short" style', () => {
expect(getWeekdayNames({ locale: 'en-GB', style: 'short' })).to.deep.equal(
s`Sun Mon Tue Wed Thu Fri Sat`,
);
expect(getWeekdayNames({ locale: 'nl-NL', style: 'short' })).to.deep.equal(
s`zo ma di wo do vr za`,
);
expect(getWeekdayNames({ locale: 'zh-CH', style: 'short' })).to.deep.equal(
s`周日 周一 周二 周三 周四 周五 周六`,
);
});
it('supports "narrow" style', () => {
expect(getWeekdayNames({ locale: 'en-GB', style: 'narrow' })).to.deep.equal(s`S M T W T F S`);
expect(getWeekdayNames({ locale: 'nl-NL', style: 'narrow' })).to.deep.equal(s`Z M D W D V Z`);
expect(getWeekdayNames({ locale: 'zh-CH', style: 'narrow' })).to.deep.equal(
s`日 一 二 三 四 五 六`,
);
});
});