fix(localize): make use of formatDate locale option to parse the date correctly (#2270)
This commit is contained in:
parent
c8093bd55b
commit
a53ded7ef8
8 changed files with 36 additions and 13 deletions
5
.changeset/neat-spiders-impress.md
Normal file
5
.changeset/neat-spiders-impress.md
Normal file
|
|
@ -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.
|
||||||
|
|
@ -10,8 +10,8 @@ import { formatDate } from '@lion/ui/localize.js';
|
||||||
import '@lion/ui/define/lion-input-date.js';
|
import '@lion/ui/define/lion-input-date.js';
|
||||||
```
|
```
|
||||||
|
|
||||||
```js preview-story
|
```html preview-story
|
||||||
export const main = () => html` <lion-input-date label="Date"></lion-input-date> `;
|
<lion-input-date label="Date" name="date"></lion-input-date>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export class LionInputDate extends LocalizeMixin(LionInput) {
|
||||||
/**
|
/**
|
||||||
* @param {string} value
|
* @param {string} value
|
||||||
*/
|
*/
|
||||||
this.parser = value => (value === '' ? undefined : parseDate(value));
|
this.parser = value => (value === '' ? undefined : parseDate(value, this.formatOptions));
|
||||||
this.formatter = formatDate;
|
this.formatter = formatDate;
|
||||||
this.defaultValidators.push(new IsDate());
|
this.defaultValidators.push(new IsDate());
|
||||||
// Just explicitly make clear we shouldn't use type 'date'
|
// Just explicitly make clear we shouldn't use type 'date'
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ import { splitDate } from './utils/splitDate.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To compute the localized date format
|
* To compute the localized date format
|
||||||
|
* @param {string} [locale]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function getDateFormatBasedOnLocale() {
|
export function getDateFormatBasedOnLocale(locale) {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {ArrayLike.<string>} dateParts
|
* @param {ArrayLike.<string>} dateParts
|
||||||
|
|
@ -35,9 +36,9 @@ export function getDateFormatBasedOnLocale() {
|
||||||
date.setDate(20);
|
date.setDate(20);
|
||||||
date.setMonth(11);
|
date.setMonth(11);
|
||||||
date.setFullYear(2012);
|
date.setFullYear(2012);
|
||||||
|
const options = locale ? { locale } : {};
|
||||||
// Strange characters added by IE11 need to be taken into account here
|
// 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' ]
|
// For Dutch locale, dateParts would match: [ 1:'20', 2:'-', 3:'12', 4:'-', 5:'2012' ]
|
||||||
const dateParts = splitDate(formattedDate);
|
const dateParts = splitDate(formattedDate);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@ import { getDateFormatBasedOnLocale } from './getDateFormatBasedOnLocale.js';
|
||||||
import { getLocalizeManager } from '../getLocalizeManager.js';
|
import { getLocalizeManager } from '../getLocalizeManager.js';
|
||||||
import { addLeadingZero } from './utils/addLeadingZero.js';
|
import { addLeadingZero } from './utils/addLeadingZero.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('../../types/LocalizeMixinTypes.js').FormatDateOptions} FormatDateOptions
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {function} fn
|
* @param {function} fn
|
||||||
*/
|
*/
|
||||||
|
|
@ -26,15 +30,16 @@ const memoizedGetDateFormatBasedOnLocale = memoize(getDateFormatBasedOnLocale);
|
||||||
* To parse a date into the right format
|
* To parse a date into the right format
|
||||||
*
|
*
|
||||||
* @param {string} dateString
|
* @param {string} dateString
|
||||||
|
* @param {FormatDateOptions} [options] Intl options are available
|
||||||
* @returns {Date | undefined}
|
* @returns {Date | undefined}
|
||||||
*/
|
*/
|
||||||
export function parseDate(dateString) {
|
export function parseDate(dateString, options) {
|
||||||
const localizeManager = getLocalizeManager();
|
const localizeManager = getLocalizeManager();
|
||||||
|
|
||||||
const stringToParse = addLeadingZero(dateString);
|
const stringToParse = addLeadingZero(dateString);
|
||||||
let parsedString;
|
let parsedString;
|
||||||
|
|
||||||
switch (memoizedGetDateFormatBasedOnLocale(localizeManager.locale)) {
|
switch (memoizedGetDateFormatBasedOnLocale(options?.locale || localizeManager.locale)) {
|
||||||
case 'day-month-year':
|
case 'day-month-year':
|
||||||
parsedString = `${stringToParse.slice(6, 10)}/${stringToParse.slice(
|
parsedString = `${stringToParse.slice(6, 10)}/${stringToParse.slice(
|
||||||
3,
|
3,
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,10 @@ import { clean } from './clean.js';
|
||||||
* To sanitize a date from IE11 handling
|
* To sanitize a date from IE11 handling
|
||||||
*
|
*
|
||||||
* @param {Date} date
|
* @param {Date} date
|
||||||
|
* @param {import('../../../types/LocalizeMixinTypes.js').FormatDateOptions} [options] Intl options are available
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function sanitizedDateTimeFormat(date) {
|
export function sanitizedDateTimeFormat(date, options) {
|
||||||
const fDate = formatDate(date);
|
const fDate = formatDate(date, options);
|
||||||
return clean(fDate);
|
return clean(fDate);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,19 @@ import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
|
||||||
|
|
||||||
describe('getDateFormatBasedOnLocale()', () => {
|
describe('getDateFormatBasedOnLocale()', () => {
|
||||||
const localizeManager = getLocalizeManager();
|
const localizeManager = getLocalizeManager();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localizeTearDown();
|
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';
|
localizeManager.locale = 'en-GB';
|
||||||
expect(getDateFormatBasedOnLocale()).to.equal('day-month-year');
|
expect(getDateFormatBasedOnLocale()).to.equal('day-month-year');
|
||||||
localizeManager.locale = 'en-US';
|
localizeManager.locale = 'en-US';
|
||||||
expect(getDateFormatBasedOnLocale()).to.equal('month-day-year');
|
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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -51,13 +51,20 @@ describe('parseDate()', () => {
|
||||||
expect(equalsDate(parseDate('14.12.1976 r.'), new Date('1976/12/14'))).to.equal(true);
|
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';
|
localizeManager.locale = 'en-GB';
|
||||||
expect(equalsDate(parseDate('31-12-1976'), new Date('1976/12/31'))).to.equal(true);
|
expect(equalsDate(parseDate('31-12-1976'), new Date('1976/12/31'))).to.equal(true);
|
||||||
localizeManager.locale = 'en-US';
|
localizeManager.locale = 'en-US';
|
||||||
expect(equalsDate(parseDate('12-31-1976'), new Date('1976/12/31'))).to.equal(true);
|
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', () => {
|
it('handles timezones of the browser and parsed date correctly', () => {
|
||||||
const referenceDate = new Date('2020/01/30');
|
const referenceDate = new Date('2020/01/30');
|
||||||
localizeManager.locale = 'nl-NL';
|
localizeManager.locale = 'nl-NL';
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue