bodar / totallylazy.js

TotallyLazy.js
Apache License 2.0
8 stars 5 forks source link

date parsing doesn't guard against unsupported locales #26

Open philwhiteuk opened 1 year ago

philwhiteuk commented 1 year ago

The dateTimeFormat function depends on the requested locale being supported by the host system which isn't always the case.

https://github.com/bodar/totallylazy.js/blob/391168f8dc122e6d46eccad830fe104bd3c63e61/src/dates/format.ts#L11-L13

By default Intl.DateTimeFormat uses a "best fit" algorithm to match the requested locale and so if the locale is not known it returns the default:

... The runtime compares it against the locales it has available and picks the best one available...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locale_identification_and_negotiation

e.g.

new Intl.DateTimeFormat('foo', { day: 'numeric', month: 'numeric', year: 'numeric', timeZone: 'UTC'}).format(Date.now())
// outputs something like '07/03/2023'

Ideally, when parsing a date, I would like a way to guard against the locale being unsupported without having to do this outside of the totallylazy library. Intl does support this through the use of Intl.DateTimeFormat.supportedLocalesOf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/supportedLocalesOf

e.g.

Intl.DateTimeFormat.supportedLocalesOf('en') // ['en']
Intl.DateTimeFormat.supportedLocalesOf('foo') // []
aballal commented 1 year ago

Maybe this is the expectation?

it('does not interchange the day and month when the locale is not supported', function () {
    // in an environment where locale "de" is not supported
    const option: Options = { day: 'numeric', month: 'numeric', year: 'numeric' };
    expect(Intl.DateTimeFormat.supportedLocalesOf('de')).to.eql([]);
    expect(parser('de', option).parse('03.06.2023')).to.not.eql(new Date('2023-03-06'));
    expect(parser('de', option).parse('03.06.2023')).to.eql(undefined);
});