Sitelet https://github.com/androidx/androidx/pull/906
Skip to content

Support ISO-8601 date/time strings in A2uiFormatDateFunction - #906

Open
zeroasterisk wants to merge 1 commit into
androidx:androidx-mainfrom
zeroasterisk:fix-a2ui-formatdate-iso-string
Open

zeroasterisk wants to merge 1 commit into
androidx:androidx-mainfrom
zeroasterisk:fix-a2ui-formatdate-iso-string

Conversation

@zeroasterisk

Copy link
Copy Markdown

A2uiFormatDateFunction.execute() only accepted the value argument as an epoch timestamp (a Number, or a numeric String), via A2uiFunctionArgParser.getLongArg(). Canonical A2UI examples send date fields as ISO-8601 strings -- e.g. specification/v1_0/catalogs/basic/examples/01_flight-status.json in a2ui-project/a2ui sends "date": "2025-12-15" and "departureTime": "2025-12-15T10:15:00Z" -- which threw A2uiException.A2uiValidationException ("Invalid 'value' argument, expected long").

This adds ISO-8601 date/date-time string parsing as a fallback when value isn't numeric, supporting date-only and date-time values (minute/second/millisecond precision, with or without a trailing Z). It reuses the same pattern list already used by androidx.a2ui.compose.ui.catalog.parseIsoDateTimeToUtcMillis (used for DateTimeInput components) so both catalog surfaces parse ISO date/time strings consistently.

Non-date, non-numeric values still throw A2uiException.A2uiValidationException, unchanged.

On the separate 'validation exception crashes the app' concern raised alongside this bug: I traced A2uiCoreExecutionContext.executeFunction() (a2ui-engine) and A2uiComponentScopeImpl.resolvePayload() (compose-runtime) -- both already wrap function execution in try/catch and route A2uiException/generic Exception to dispatchError()/reportError() instead of propagating. So a thrown A2uiValidationException from formatDate does not crash the app through those paths; it is reported back to the agent as intended. No change was needed there.

Test: Ported the upstream A2uiFormatDateFunctionTest unmodified into a standalone Kotlin/JVM harness (extracted a2ui-model sources, JUnit4 + Truth, since the sandbox available to prepare this change has no Android SDK / full Gradle build) and ran it against both the old and new implementation:

  • Before the fix: ISO-8601 string values threw A2uiValidationException as described in the bug report.
  • After the fix: all 13 pre-existing tests still pass unmodified (locale handling, all numeric value types, ISO output format, all-tokens pattern, all 4 existing exception-throwing cases), plus 4 new tests added to A2uiFormatDateFunctionTest.kt covering ISO date-only, ISO instant, ISO instant with milliseconds, and confirming non-date garbage strings still throw A2uiValidationException. 17/17 pass.

Please re-run ./gradlew :a2ui:a2ui-model:test in CI/Treehugger to confirm on the real Android toolchain.

A2uiFormatDateFunction.execute() required the 'value' argument to be an
epoch timestamp (seconds or milliseconds, as a Number or numeric String).
Canonical A2UI examples (e.g. specification/v1_0/catalogs/basic/examples/
01_flight-status.json in a2ui-project/a2ui) send date fields as ISO-8601
strings (e.g. "2025-12-15", "2025-12-15T10:15:00Z"), which
A2uiFunctionArgParser.getLongArg() rejects with an
A2uiException.A2uiValidationException.

Add ISO-8601 date/date-time string parsing (date-only, minute, second,
and millisecond precision, with or without a trailing 'Z') as a fallback
when the value isn't numeric, reusing the same pattern list already used
by androidx.a2ui.compose.ui.catalog.parseIsoDateTimeToUtcMillis for
DateTimeInput components, so both catalog surfaces parse ISO date/time
strings consistently.

Non-date, non-numeric strings continue to throw
A2uiException.A2uiValidationException as before -- callers that already
run function execution through A2uiCoreExecutionContext.executeFunction()
route this to dispatchError() rather than crashing, so no separate
crash-handling change was needed there; it verified there.

Test: ./gradlew :a2ui:a2ui-model:testDebugUnitTest (unit tests updated to
cover ISO date-only, ISO instant, ISO instant with milliseconds, and
verifying invalid strings still throw A2uiValidationException). All 13
pre-existing tests plus 4 new ones verified locally against a standalone
Kotlin/JVM compile of the affected sources (JUnit4 + Truth), since the
sandboxed environment used to prepare this change has no Android SDK / full
Gradle build available.

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant