Skip to content

Add test for date/time separating literal for { dateStyle: "medium" } #3776

Closed

Description

@frontsideair

I have found an implementation inconsistency between Safari (WebKit) and Chrome (V8) where formatting a date with time in en-US locale, if dateStyle is medium, the literal separating the date and time is different.

For example:

new Intl.DateTimeFormat("en-US", {dateStyle: "medium", timeStyle: "short"}).format(new Date())
// Google Chrome Version 109.0.5414.119 (Official Build) (arm64)
> Jan 30, 2023, 6:50 PM
// Safari Version 16.1 (18614.2.9.1.12)
> Jan 30, 2023 at 6:50 PM

Here's a playground for easy reproduction.

I wonder which behavior is correct, but the spec is dense and I thought that there should be a test for this case. If you don't think this is the case, please let me know where I should open a bug report.

Activity

  1. ptomato commented on Feb 1, 2023

    @ptomato
    Member

    Hi @frontsideair, thanks for the report!

    It looks like the version with "at" should occur with dateStyle: "full" or dateStyle: "long": https://github.com/unicode-org/cldr/blob/main/common/main/en.xml#L2437-L2463

    The standard disclaimer that I give when we get questions about the output of Intl formatter methods and toLocaleString() is that these formats are "implementation-defined" which technically puts this out of scope for test262 because an engine could pretty much have any value they like and still be compliant. In practice, of course, that's not what happens: engines either have no locale data and no Intl object at all, or sensible locale data.

    That said, we do have some locale-specific tests for particular bugs, and this isn't the first report of unexpected localization results in Safari 16.1 that I've heard of, so I'll ask around to see if anyone knows more about why this might be the case.

  2. frontsideair commented on Feb 1, 2023

    @frontsideair
    Author

    Thanks for pointing me to the right direction, seems like the issue is with CLDR compliance, not DateTimeFormat, but it still affects the outcome. Sorry to hear that this happened before with Safari.

    I wouldn’t mind too much since the output is acceptable to me, but to give more context about my issue is that when server-rendering a React application, there’s a hydration mismatch between Node.js and Safari, and React throws an error at runtime. I already have a workaround in place, but I didn’t expect it to happen at all.

    Hope this gets fixed soon, and if you learn where can I open an issue please let me know.

  3. ptomato commented on Feb 14, 2023

    @ptomato
    Member

    I have done some digging and found out some more information.

    The major browsers all have their own minor customizations to the CLDR / ICU data. In this particular case, it's a consequence of Apple modifying ICU to conform to the Apple Human Interface Guidelines, to make Safari consistent with the UI in the rest of their operating system. (The source code for Apple's modified ICU is here in case you feel like digging further.) But I learned it's not just Safari, Chrome also makes customizations to ICU which don't ship in Node.js! Despite them sharing a JS engine, they use different locale data, shown here in some locales that have different default numbering systems:

    Chromium 109

    new Date().toLocaleString('my')
    '13/02/2023, 15:47:58'
    new Date().toLocaleString('ar')
    '13‏/2‏/2023 3:51:13 م'

    Node.js 18.9.0

    new Date().toLocaleString('my')
    '၁၃-၀၂-၂၀၂၃ ၁၅:၄၇:၃၇'
    new Date().toLocaleString('ar')
    '١٣‏/٢‏/٢٠٢٣, ٣:٥١:٠٥ م'

    This is all permitted by the specification, due to this part being "implementation-defined". Given the intentional divergence here I think it probably wouldn't be helpful for the landscape of JS implementations to have a test262 test.

    I'm not sure what I'd recommend your next steps should be. For now, the workaround is probably the right thing to do here when rendering an application server-side. It might be good to bring the problem to the attention of React so that they can take such mismatches into account when hydrating pages. You could also try opening a discussion on the issue tracker of tc39/ecma402 pointing out that different platforms' customization of ICU causes this type of error, with the goal of tightening the specification to disallow such customizations. (This isn't the only report we've gotten of a server-rendered page failing to hydrate.) But I wouldn't give that a high probability of success — it seems like there are good reasons for browsers to want to make these customizations. Maybe it would be possible to specify one special 'testing' locale where cutomizations are not allowed.

  4. frontsideair commented on Feb 14, 2023

    @frontsideair
    Author

    Thanks for the detailed report, it was very helpful. It's sad to see that there are more divergences than I imagined, but I understand that it's allowed to be implementation defined and it makes sense that there cannot be a test for this case.

    I likely won't report an issue to ecma402, but may bring this up to the React project, which seems like the right party for it. I'm happy with my current workaround, and seeing that Chrome has modifications too makes it even more necessary.

    Again, thanks for looking into this!

  5. frontsideair commented on Feb 28, 2023

    @frontsideair
    Author

    After some digging, I understand that the supported way to handle these inconsistencies with React is to suppress the hydration warnings at expected places.

    I guess there's no way to ensure the client and the server will behave exactly the same, so inevitable some parts will end up different. React itself will render a subtree up to a suspense boundary when it encounters a hydration mismatch, so uncaught mismatches won't create a big problem if there are fine grained suspense boundaries in the app.

  6. ptomato commented on Feb 28, 2023

    @ptomato
    Member

    Thanks for following up, this is good advice for anyone else encountering the same problem.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions