Skip to content

fix(core): honor TR35 quoted literals and EEE in formatDate - #3787

Open
karolkulesza wants to merge 5 commits into
a2ui-project:mainfrom
karolkulesza:fix/formatdate-tr35-literals
Open

karolkulesza wants to merge 5 commits into
a2ui-project:mainfrom
karolkulesza:fix/formatdate-tr35-literals

Conversation

@karolkulesza

Copy link
Copy Markdown
Contributor

Description

formatDate takes a Unicode TR35 pattern, but the hand-written tokenizers in web_core, Python a2ui_core (v0.9 and v1.0) and Dart a2ui_core didn't know quoted literals or EE/EEE. With 2026-02-02T15:17:09Z:

  • "MMM d 'at' h:mm a" gave Feb 2 'PMt' 3:17 PM: the a in 'at' was read as AM/PM and the quotes were kept.
  • "EEE, MMM d" gave MonMonMon, Feb 2.
  • "h 'o''clock'" gave 3 'o''clock'.

Two v0.9.1 basic catalog examples use a quoted literal (16_workout-summary.json, 30_live-invitation-builder.json), so both render wrong today. Swift uses DateFormatter and was already correct.

Changes:

  • The token regex in each SDK now matches '' (an apostrophe) and '...' (a literal, where '' inside stands for an apostrophe) before any pattern letter. An unclosed quote runs to the end of the pattern, as in date-fns, which web_core used before 0.12.0. EEE and EE give the abbreviated weekday, like E.
    • web_core: src/common/basic_functions.ts
    • Python: basic_catalog/v0_9/function_impls.py and basic_catalog/v1_0/function_impls.py
    • Dart: lib/src/basic_catalog/locale_formatting.dart
  • conformance/core/functions.yaml: three new cases, test_evaluate_function_format_date_quoted_literal, ..._escaped_apostrophe and ..._short_weekday. They use noon UTC values and keep hour tokens inside the quotes, so they give the same result in any host time zone (Swift still formats in the local zone, see fix(swift): keep the written wall-clock time in formatDate and accept timestamps without an offset #3380).
  • Unit tests in each SDK for the hour-based patterns from the issue and an unclosed quote.
  • ## Unreleased entries in the web_core, Python a2ui_core and Dart a2ui_core changelogs.

The format description in the basic catalog doesn't mention quoting or EEE. Changing it regenerates fixtures in every SDK, so I left it for a follow-up.

Testing:

  • The new conformance cases fail on main in web_core, Python and Dart, and pass with the change.
  • web_core: yarn test (0 failures), node tests/conformance/conformance_test.mjs, eslint and prettier on the touched files.
  • Python: uv run pytest from the repo root (3783 passed), uv run pyink --check ., uv run --all-packages mypy ..
  • Dart (dart/a2ui_core): dart test, dart analyze, dart format --set-exit-if-changed.
  • Swift (swift/core): swift test --filter BasicCatalogConformance passes the new cases unchanged with TZ set to UTC, Europe/Warsaw, America/Los_Angeles and Asia/Tokyo.

Fixes #2937

Pre-launch Checklist

One time:

For this PR:

  • I have updated the relevant CHANGELOG.md file.
  • I updated/added relevant documentation. (No docs change: formatDate is documented as taking a TR35 pattern, which already includes quoting and EEE.)
  • My code changes (if any) have tests.
  • If my branch is on a fork, I have verified that scripts/e2e_test.sh passes.

If you need help, consider asking for advice on the discussion board.

The formatDate tokenizers in web_core, Python a2ui_core (v0.9 and v1.0)
and Dart a2ui_core did not know TR35 quoted literals or EE/EEE, so
"MMM d 'at' h:mm a" rendered "Feb 2 'PMt' 3:17 PM" and "EEE" rendered
"MonMonMon". Each token regex now matches '' as an apostrophe and '...'
as a literal (with '' inside it as an apostrophe; an unclosed quote runs
to the end, as in date-fns), and maps EEE and EE to the short weekday.

Add time-zone-neutral functions.yaml cases for a quoted literal, an
escaped apostrophe and EEE/EE, plus unit tests in each SDK. Swift uses
DateFormatter and passes the new cases unchanged.

Fixes a2ui-project#2937

@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 updates the formatDate function across Dart, Python, and TypeScript implementations to support TR35 pattern tokens, quoted literals (where text in single quotes is copied through literally and '' is rendered as a single apostrophe), and short weekday tokens (EEE and EE). Unit tests and conformance tests have been added to verify these changes, and the changelogs have been updated accordingly. There are no review comments, so I have no additional feedback to provide.

@github-actions github-actions Bot added the status: needs-triage auto-managed: https://github.com/a2ui-project/a2ui/blob/main/scripts/triage.mjs label Oct 30, 2026

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

Labels

status: needs-triage auto-managed: https://github.com/a2ui-project/a2ui/blob/main/scripts/triage.mjs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: formatDate breaks quoted literals and EEE since date-fns was removed

1 participant