moment / luxon

⏱ A library for working with dates and times in JS
https://moment.github.io/luxon
MIT License
15.47k stars 730 forks source link

Format "DDD" with locale "ES" use Incorrect Fixed Date Format #1645

Open dev2xl opened 4 months ago

dev2xl commented 4 months ago

Describe the bug

If you use DateTime.expandFormat("DDD", { locale: "en" }) you get MMMM d, yyyyy and that's correct (although why 5 y instead of 4?). But when you use it with the locale es like DateTime.expandFormat("DDD", { locale: "es" }) you get d de abril de 2019 and this is wrong. Is only allowing to specify the day, the rest month and year are fixed to the current month and the year 2019.

SoDateTime.fromFormat("2 de abril de 2019", "DDD).isValid will be true, but changing the month or year will return invalid since that part is fixed internally on the library.

To Reproduce

DateTime.expandFormat("DDD", { locale: "es" })
DateTime.fromFormat("2 de abril de 2024", "DDD")

Actual vs Expected behavior DateTime.expandFormat("DDD", { locale: "es" }) should return d de MMMM de yyyy DateTime.fromFormat("2 de abril de 2024", "DDD").isValid should return true

Desktop (please complete the following information):

diesieben07 commented 4 months ago

I don't own a Mac to test this on, however on Chrome I cannot reproduce this. In the environment where you experience this, can you please provide the output of the following:

new Intl.DateTimeFormat('es', { year: 'numeric', month: 'long', day: 'numeric' }).formatToParts(new Date(1555555555555));

If it functions correctly, it should output:

[
    {
        "type": "day",
        "value": "18"
    },
    {
        "type": "literal",
        "value": " de "
    },
    {
        "type": "month",
        "value": "abril"
    },
    {
        "type": "literal",
        "value": " de "
    },
    {
        "type": "year",
        "value": "2019"
    }
]
dev2xl commented 4 months ago

@diesieben07 it returns

[{
  type: "day",
  value: "17"
}, {
  type: "literal",
  value: " de "
}, {
  type: "month",
  value: "abril"
}, {
  type: "literal",
  value: " de "
}, {
  type: "year",
  value: "2019"
}]

And new Intl.DateTimeFormat('es', { year: 'numeric', month: 'long', day: 'numeric' }).formatToParts(new Date(1722192629000)) returns:

[{
  type: "day",
  value: "28"
}, {
  type: "literal",
  value: " de "
}, {
  type: "month",
  value: "julio"
}, {
  type: "literal",
  value: " de "
}, {
  type: "year",
  value: "2024"
}]

In my opinion the issue is related to the specific format DDD. It has fixed the parts for the month and the year with the locale es.

diesieben07 commented 4 months ago

Thank you for the info. Unfortunately that output suggests DDD should work perfectly fine for you. Some background information: When Luxon wants to format a date using a "macro token" (such as DDD) then Luxon uses formatToParts (as shown in my example code) to ask the browser how the format should look (DDD is mapped internally to { year: 'numeric', month: 'long', day: 'numeric' } by Luxon for this). Then Luxon will look at the type fields in the resulting value to figure out which parts of the formatted date it needs to keep as literal and which represent the specific date values. You can see the result of this expansion process by calling DateTime.expandFormat("DDD"), which should produce "d de MMMM de yyyyy" in your example.

Unfortunately I really don't know how to proceed here, because I cannot reproduce this issue.