Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to parse a luxon's formatted DateTime with a locale having a different numbering system #1120

Open
brboi opened this issue Jan 17, 2022 · 3 comments

Comments

@brboi
Copy link

brboi commented Jan 17, 2022

Describe the bug
Unable to parse a luxon's formatted DateTime with a locale having a different numbering system

To Reproduce
A minimal code example that triggers the problem:

dt = luxon.DateTime.fromISO('2014-08-06T13:07:04.054')
formatted = dt.toFormat("dd MMM, yyyy hh:mm:ss", {locale:"ar-001"}) // formatted becomes  "٠٦ أغسطس, ٢٠١٤ ٠١:٠٧:٠٤"
reverseOperation = luxon.DateTime.fromFormat(formatted, "dd MMM, yyyy hh:mm:ss", {locale:"ar-001"}) // yields an invalid DateTime object

fromFormatExplain gives us the following object where we could clearly see that the regex would never match as the numbering system is not the same as the \d regexp token:

{
    input: "٠٦ أغسطس, ٢٠١٤ ٠١:٠٧:٠٤",
    tokens: [
        { literal: false, val: "dd" },
        { literal: false, val: " " },
        { literal: false, val: "MMM" },
        { literal: false, val: "," },
        { literal: false, val: " " },
        { literal: false, val: "yyyy" },
        { literal: false, val: " " },
        { literal: false, val: "hh" },
        { literal: false, val: ":" },
        { literal: false, val: "mm" },
        { literal: false, val: ":" },
        { literal: false, val: "ss" }
    ],
    regex: /^(\d{2})(\ )(يناير|فبراير|مارس|أبريل|مايو|يونيو|يوليو|أغسطس|سبتمبر|أكتوبر|نوفمبر|ديسمبر)(\,)(\ )(\d{4})(\ )(\d{2})(:)(\d{2})(:)(\d{2})$/i,
    rawMatches: null,
    matches: {},
    result: {},
    zone: null
}

Actual vs Expected behavior
Actual:

  • using same format and options, formatting a DateTime and then format the obtained string into a DateTime does not work

Expected:

  • using same format and options, formatting a DateTime and then format the obtained string into a DateTime should work

Desktop (please complete the following information):

  • OS: Arch Linux
  • Browser: tried with Firefox 96.0.1 and Chromium 97.0.4692.71
  • Luxon version: 2.3.0
  • Your timezone: Europe/Brussels
@anwalkers
Copy link

anwalkers commented Feb 23, 2022

@brboi I am experiencing the same issue with arabic fromFormat. In my tests I am noticing that the zone is null. I tried setZone: true and setting it to a known time zone.

I added the following tests to the luxon tokenParse.test.js

  const ex3_1 = DateTime.fromFormatExplain("١١:١١ ص", "h:m a", {
    locale: "ar",
    numberingSystem: "arab",
    format: 12
  });
  expect(ex3_1.hour).toBe(11);
  expect(ex3_1.minute).toBe(11);
  expect(ex3_1.matches).toEqual({
    h: 11,
    m: 11
  });

I get this output

image

And testing the 24 hour format with this test

  const ex3_2 = DateTime.fromFormatExplain("٢١:١١", "h:m a", {
    locale: "ar",
    numberingSystem: "arab",
    format: 24
  });
  expect(ex3_2.hour).toBe(21);
  expect(ex3_2.minute).toBe(11);
  expect(ex3_2.matches).toEqual({
    h: 21,
    m: 11
  });

I get this output

image

@icambron
Copy link
Member

Yeah, this is a general problem with other character sets; they don't match the \d regex. I haven't figure out how to resolve that yet.

@diesieben07
Copy link
Collaborator

The mechanism for this is already present and was added in 2019. But it only works if you specify the numbering system manually, it is not inferred from the locale. That would be easy to add though.
For now you can use the following workaround:

const locale = 'ar-001';
const dt = DateTime.fromISO('2014-08-06T13:07:04.054');

const formatted = dt.toFormat("dd MMM, yyyy hh:mm:ss", {locale: locale});

const localeOptions = new Intl.DateTimeFormat(locale).resolvedOptions();
const reverse = DateTime.fromFormat(formatted, "dd MMM, yyyy hh:mm:ss", {locale: locale, numberingSystem: localeOptions.numberingSystem});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants