diff --git a/.changeset/neat-spiders-impress.md b/.changeset/neat-spiders-impress.md new file mode 100644 index 000000000..461e621f3 --- /dev/null +++ b/.changeset/neat-spiders-impress.md @@ -0,0 +1,5 @@ +--- +'@lion/ui': patch +--- + +[localize] make use of formatDate locale option to parse the date correctly, which prevents day and month jumping in the input-amount when e.g. en-GB is used on the html tag and en-US is used to format the date. diff --git a/docs/components/input-date/overview.md b/docs/components/input-date/overview.md index cac209771..e187401f4 100644 --- a/docs/components/input-date/overview.md +++ b/docs/components/input-date/overview.md @@ -10,8 +10,8 @@ import { formatDate } from '@lion/ui/localize.js'; import '@lion/ui/define/lion-input-date.js'; ``` -```js preview-story -export const main = () => html` `; +```html preview-story + ``` ## Features diff --git a/packages/ui/components/input-date/src/LionInputDate.js b/packages/ui/components/input-date/src/LionInputDate.js index 3191033c5..62756dfa4 100644 --- a/packages/ui/components/input-date/src/LionInputDate.js +++ b/packages/ui/components/input-date/src/LionInputDate.js @@ -21,7 +21,7 @@ export class LionInputDate extends LocalizeMixin(LionInput) { /** * @param {string} value */ - this.parser = value => (value === '' ? undefined : parseDate(value)); + this.parser = value => (value === '' ? undefined : parseDate(value, this.formatOptions)); this.formatter = formatDate; this.defaultValidators.push(new IsDate()); // Just explicitly make clear we shouldn't use type 'date' diff --git a/packages/ui/components/localize/src/date/getDateFormatBasedOnLocale.js b/packages/ui/components/localize/src/date/getDateFormatBasedOnLocale.js index c5e976246..a895298c6 100644 --- a/packages/ui/components/localize/src/date/getDateFormatBasedOnLocale.js +++ b/packages/ui/components/localize/src/date/getDateFormatBasedOnLocale.js @@ -3,9 +3,10 @@ import { splitDate } from './utils/splitDate.js'; /** * To compute the localized date format + * @param {string} [locale] * @returns {string} */ -export function getDateFormatBasedOnLocale() { +export function getDateFormatBasedOnLocale(locale) { /** * * @param {ArrayLike.} dateParts @@ -35,9 +36,9 @@ export function getDateFormatBasedOnLocale() { date.setDate(20); date.setMonth(11); date.setFullYear(2012); - + const options = locale ? { locale } : {}; // Strange characters added by IE11 need to be taken into account here - const formattedDate = sanitizedDateTimeFormat(date); + const formattedDate = sanitizedDateTimeFormat(date, options); // For Dutch locale, dateParts would match: [ 1:'20', 2:'-', 3:'12', 4:'-', 5:'2012' ] const dateParts = splitDate(formattedDate); diff --git a/packages/ui/components/localize/src/date/parseDate.js b/packages/ui/components/localize/src/date/parseDate.js index 27cb61f80..671c19309 100644 --- a/packages/ui/components/localize/src/date/parseDate.js +++ b/packages/ui/components/localize/src/date/parseDate.js @@ -2,6 +2,10 @@ import { getDateFormatBasedOnLocale } from './getDateFormatBasedOnLocale.js'; import { getLocalizeManager } from '../getLocalizeManager.js'; import { addLeadingZero } from './utils/addLeadingZero.js'; +/** + * @typedef {import('../../types/LocalizeMixinTypes.js').FormatDateOptions} FormatDateOptions + */ + /** * @param {function} fn */ @@ -26,15 +30,16 @@ const memoizedGetDateFormatBasedOnLocale = memoize(getDateFormatBasedOnLocale); * To parse a date into the right format * * @param {string} dateString + * @param {FormatDateOptions} [options] Intl options are available * @returns {Date | undefined} */ -export function parseDate(dateString) { +export function parseDate(dateString, options) { const localizeManager = getLocalizeManager(); const stringToParse = addLeadingZero(dateString); let parsedString; - switch (memoizedGetDateFormatBasedOnLocale(localizeManager.locale)) { + switch (memoizedGetDateFormatBasedOnLocale(options?.locale || localizeManager.locale)) { case 'day-month-year': parsedString = `${stringToParse.slice(6, 10)}/${stringToParse.slice( 3, diff --git a/packages/ui/components/localize/src/date/utils/sanitizedDateTimeFormat.js b/packages/ui/components/localize/src/date/utils/sanitizedDateTimeFormat.js index 78e26df2d..34bedae91 100644 --- a/packages/ui/components/localize/src/date/utils/sanitizedDateTimeFormat.js +++ b/packages/ui/components/localize/src/date/utils/sanitizedDateTimeFormat.js @@ -5,9 +5,10 @@ import { clean } from './clean.js'; * To sanitize a date from IE11 handling * * @param {Date} date + * @param {import('../../../types/LocalizeMixinTypes.js').FormatDateOptions} [options] Intl options are available * @returns {string} */ -export function sanitizedDateTimeFormat(date) { - const fDate = formatDate(date); +export function sanitizedDateTimeFormat(date, options) { + const fDate = formatDate(date, options); return clean(fDate); } diff --git a/packages/ui/components/localize/test/date/getDateFormatBasedOnLocale.test.js b/packages/ui/components/localize/test/date/getDateFormatBasedOnLocale.test.js index fb1c90820..fbe6a6ca9 100644 --- a/packages/ui/components/localize/test/date/getDateFormatBasedOnLocale.test.js +++ b/packages/ui/components/localize/test/date/getDateFormatBasedOnLocale.test.js @@ -7,15 +7,19 @@ import { localizeTearDown } from '@lion/ui/localize-test-helpers.js'; describe('getDateFormatBasedOnLocale()', () => { const localizeManager = getLocalizeManager(); - beforeEach(() => { localizeTearDown(); }); - it('returns the positions of day, month and year', async () => { + it('returns the positions of day, month and year with locale set globally', async () => { localizeManager.locale = 'en-GB'; expect(getDateFormatBasedOnLocale()).to.equal('day-month-year'); localizeManager.locale = 'en-US'; expect(getDateFormatBasedOnLocale()).to.equal('month-day-year'); }); + + it('returns the positions of day, month and year with given locale', async () => { + expect(getDateFormatBasedOnLocale('en-GB')).to.equal('day-month-year'); + expect(getDateFormatBasedOnLocale('en-US')).to.equal('month-day-year'); + }); }); diff --git a/packages/ui/components/localize/test/date/parseDate.test.js b/packages/ui/components/localize/test/date/parseDate.test.js index 64e535c10..a42f62179 100644 --- a/packages/ui/components/localize/test/date/parseDate.test.js +++ b/packages/ui/components/localize/test/date/parseDate.test.js @@ -51,13 +51,20 @@ describe('parseDate()', () => { expect(equalsDate(parseDate('14.12.1976 r.'), new Date('1976/12/14'))).to.equal(true); }); - it('handles different locales', () => { + it('handles different locales globally set', () => { localizeManager.locale = 'en-GB'; expect(equalsDate(parseDate('31-12-1976'), new Date('1976/12/31'))).to.equal(true); localizeManager.locale = 'en-US'; expect(equalsDate(parseDate('12-31-1976'), new Date('1976/12/31'))).to.equal(true); }); + it('handles different locales as option', () => { + const optionEnGb = { locale: 'en-GB' }; + expect(equalsDate(parseDate('31-12-1976', optionEnGb), new Date('1976/12/31'))).to.equal(true); + const optionEnUs = { locale: 'en-US' }; + expect(equalsDate(parseDate('12-31-1976', optionEnUs), new Date('1976/12/31'))).to.equal(true); + }); + it('handles timezones of the browser and parsed date correctly', () => { const referenceDate = new Date('2020/01/30'); localizeManager.locale = 'nl-NL';