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

Intl.DateTimeFormat does not format 2-digit hours correctly #1537

Open
MrPancakes39 opened this issue Oct 13, 2024 · 1 comment
Open

Intl.DateTimeFormat does not format 2-digit hours correctly #1537

MrPancakes39 opened this issue Oct 13, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@MrPancakes39
Copy link

Bug Description

When using the Intl.DateTimeFormat API in JavaScript to format dates and times, there is an inconsistency in the behavior when the hour12 option is set to true or when the provided locale uses a 12-hour clock by default, in combination with the hour option set to "2-digit".

Note: This bug seems to effect all locales but I only tested the ones below:

  • English: en-US (12 hours by default)
  • German: de-DE (24 hours by default)
  • Arabic: ar-LB (non-latin characters)

Steps To Reproduce

  1. Use the Intl.DateTimeFormat API to format a date.
  2. Set the hour option to "2-digit".
  3. Set the hour12 option to true or provide a locale that uses a 12-hour clock by default (e.g., "en-US").
  4. Observe that single-digit hours are formatted without leading zeros.

Run the following code example:

const hour1 = new Intl.DateTimeFormat("en-US", {
  hour: "2-digit",
}).format(new Date("2024-10-30 19:00"));

console.log(hour1);

// OR

const hour2 = new Intl.DateTimeFormat("fr-FR", {
  hour: "2-digit",
  hour12: true,
}).format(new Date("2024-10-30 19:00"));

console.log(hour2);

Assert that it prints 7 PM instead of 07 PM.

The Expected Behavior

When the hour option is set to "2-digit", it is expected that the formatted hour will always have two digits, including a leading zero for single-digit hours (e.g., "01", "02", ..., "12").

Actual Behavior

When hour12 is set to true or the provided locale uses a 12-hour clock by default, the "2-digit" option for hour is ignored. The formatted hour is displayed with a single digit for single-digit hours (e.g., "1", "2", ..., "12") without a leading zero.

This bug only affects the 12-hour clock format. When using a 24-hour clock format, the "2-digit" option works as expected, displaying hours with leading zeros (e.g., "00", "01", ..., "23").

Temporary Example Workaround

function workaround(date: Date) {
  const locale = "en-US";

  const parts = new Intl.DateTimeFormat(locale, {
    hour: "2-digit",
    minute: "2-digit",
    hour12: true,
  }).formatToParts(date);

  const hourPart = parts.find((part) => part.type === "hour")!;
  const hourIn24Format = new Intl.DateTimeFormat(locale, {
    hour: "2-digit",
    hour12: false,
  })
    .formatToParts(date)
    .find((p) => p.type === "hour")!.value;
  if (hourPart.value !== hourIn24Format) {
    const tmp = new Date(date);
    tmp.setHours(tmp.getHours() % 12);
    const hour24 = new Intl.DateTimeFormat(locale, {
      hour: "2-digit",
      hour12: false,
    }).format(tmp);
    hourPart.value = hour24;
  }

  return parts.map((part) => part.value).join("");
}

const hour1 = new Intl.DateTimeFormat("en-US", {
  hour: "2-digit",
  minute: "2-digit",
  hour12: true,
}).format(new Date("2024-10-30 19:00"));
const hour2 = workaround(new Date("2024-10-30 19:00"));

console.log(hour1, hour2); // prints 7:00 PM 07:00 PM

Note: The above isn't simply padding the string with zeros because that only works in latin languages.

Output of npx react-native info:

Note: The output below is from the project I am currently working on using expo.
I did created a blank new project with "react-native": "^0.75.4" (latest version ATTOW) and the issue persists.

System:
  OS: Linux 6.9 Pop!_OS 22.04 LTS
  CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  Memory: 2.24 GB / 15.49 GB
  Shell:
    version: 3.3.1
    path: /usr/bin/fish
Binaries:
  Node:
    version: 20.15.0
    path: ~/.nvm/versions/node/v20.15.0/bin/node
  Yarn:
    version: 1.22.22
    path: ~/.nvm/versions/node/v20.15.0/bin/yarn
  npm:
    version: 10.8.1
    path: ~/.nvm/versions/node/v20.15.0/bin/npm
  Watchman:
    version: 4.9.0
    path: /usr/bin/watchman
SDKs:
  Android SDK: Not Found
IDEs:
  Android Studio: AI-241.15989.150.2411.11792637
Languages:
  Java:
    version: 17.0.12
    path: /usr/bin/javac
  Ruby:
    version: 3.0.2
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.74.5
    wanted: 0.74.5
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: Not found
  newArchEnabled: false
@MrPancakes39 MrPancakes39 added the bug Something isn't working label Oct 13, 2024
@lavenzg
Copy link
Contributor

lavenzg commented Oct 25, 2024

I can reproduce it on MacOS, on which it's caused by incorrectly used platform APIs. Probably a different reason for Linux. We'll look into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants