Skip to content

[intl4x] Support TimePrecision.minuteOptional on ECMA - #1106

Open
mosuem wants to merge 5 commits into
dart-lang:mainfrom
mosuem:fix-intl4x-minute-optional-ecma
Open

mosuem wants to merge 5 commits into
dart-lang:mainfrom
mosuem:fix-intl4x-minute-optional-ecma

Conversation

@mosuem

@mosuem mosuem commented Oct 7, 2026

Copy link
Copy Markdown
Member

Note

This PR was generated by an AI coding agent (Jetski) on behalf of @mosuem.

On ECMA (datetime_format_ecma.dart), TimePrecision.minuteOptional was mapped to minute: 'numeric' via _style(timePrecision, TimePrecision.minute) because TimePrecision.minuteOptional.index >= TimePrecision.minute.index, so :00 was always displayed even when datetime.minute == 0 in 12-hour locales (e.g. '4:00 AM' instead of '4 AM').

In ICU4X (TimePrecision::MinuteOptional), minutes are omitted when minute == 0 and the resolved hour cycle is 12-hour (h11/h12), and retained when minute != 0 or in 24-hour clock formats (14:00).

Changes:

  • Pass timePrecision into _FormatterECMA._ for t, mdt, ymdt, and ymdet.
  • When timePrecision == TimePrecision.minuteOptional, datetime.minute == 0, and dateTimeFormat.resolvedOptions().hour12 == true, format using options with minute omitted (both for non-zoned and zoned formatters).
  • Clone _options via Object.assign in _DateTimeJSOptions.withTimeZone and _DateTimeJSOptions.withoutMinute so the base options object is not mutated in place.
  • Fix the doc comment on TimePrecision.minuteOptional in datetime_format_options.dart (which previously said "optional seconds" instead of "optional minutes").
  • Add tests in test/datetime_format_test.dart covering TimePrecision.minuteOptional with zero and non-zero minutes in 12-hour, 24-hour, and zoned formats.

Verified locally: dart analyze --fatal-infos, dart format --output=none --set-exit-if-changed ., dart test (VM), and dart test -p node -x ecmaUnsupported pass.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request improves the intl4x package's ECMA date-time formatting by aligning TimePrecision.minuteOptional behavior with ICU4X standards. It ensures that minutes are omitted when they are zero in 12-hour clock formats, while maintaining standard behavior for 24-hour formats and non-zero minutes. The changes involve updating the internal JS interop layer to support dynamic option cloning and conditional formatting logic.

Highlights

  • ECMA Time Formatting Logic: Implemented logic to conditionally omit minutes in ECMA-based date-time formatting when using TimePrecision.minuteOptional in 12-hour locales with zero minutes.
  • API Enhancements: Added withoutMinute() and resolvedOptions() methods to the JS interop layer to allow dynamic manipulation and inspection of date-time formatting options.
  • Documentation and Testing: Corrected the doc comment for TimePrecision.minuteOptional and added comprehensive tests covering 12-hour, 24-hour, and zoned formats.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements support for TimePrecision.minuteOptional in the ECMA datetime formatter, allowing minutes to be omitted when they are zero in 12-hour formats. It introduces a JS interop helper _assign to clone options and adds comprehensive test coverage for the new precision option. The review feedback highlights two key performance optimizations: caching the hour12 resolved option as a late final field to avoid expensive JS interop calls on every format invocation, and refactoring withTimeZone to accept an optional omitMinute parameter to prevent redundant object cloning.

Comment on lines +157 to +160
bool _shouldOmitMinute(DateTime datetime) =>
_timePrecision == TimePrecision.minuteOptional &&
datetime.minute == 0 &&
(dateTimeFormat.resolvedOptions().hour12 ?? false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Calling dateTimeFormat.resolvedOptions() on every format call is expensive because it is a JS interop call that queries the engine's internal formatter state and allocates a new JS object. Since the hour cycle configuration of the formatter does not change after construction, we should cache this value as a late final field in _FormatterECMA.

Suggested change
bool _shouldOmitMinute(DateTime datetime) =>
_timePrecision == TimePrecision.minuteOptional &&
datetime.minute == 0 &&
(dateTimeFormat.resolvedOptions().hour12 ?? false);
late final bool _is12Hour = dateTimeFormat.resolvedOptions().hour12 ?? false;
bool _shouldOmitMinute(DateTime datetime) =>
_timePrecision == TimePrecision.minuteOptional &&
datetime.minute == 0 &&
_is12Hour;

Comment on lines 210 to 216
final options = omitMinute
? formatter._optionsJS.withoutMinute()
: formatter._optionsJS;
return _DateTimeFormat(
localeJS,
formatter._optionsJS.withTimeZone(timeZoneType, timeZone),
options.withTimeZone(timeZoneType, timeZone),
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use the optimized withTimeZone method with the omitMinute parameter to avoid cloning the options object twice.

    return _DateTimeFormat(
      localeJS,
      formatter._optionsJS.withTimeZone(
        timeZoneType,
        timeZone,
        omitMinute: omitMinute,
      ),
    );

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants