Skip to content

RFC 3339 wire coercion for temporal types

Choose a tag to compare

@mgerzabek mgerzabek released this 06 May 16:35
· 6 commits to main since this release

Note: this release contains a wire-format change (UI5 consumers using targetType: 'any' workarounds will see different bytes on the wire). It ships as a patch because all three current consumers (laravelui5/core, laravelui5/sdk, pragmatiqu/timesheet.biz) are in-house and patched in lock-step with the release. SemVer credit is spent here deliberately; a future release that crosses the public funnel boundary should bump the major.

Fixed

  • Edm.DateTimeOffset / Edm.Date / Edm.TimeOfDay wire format. Row-emission path now coerces declared temporal columns to OData v4 / RFC 3339 strings before JSON encoding. Previously, MySQL DATETIME/DATE/TIME values (e.g. 2026-05-05 12:34:56) passed through unchanged — invalid per the spec, returning NaN from Date.parse() in Safari and silently coerced to local time in Chrome.

Coercion happens via Carbon::parse(...):

  • Edm.DateTimeOffset->toRfc3339String()
  • Edm.Date->toDateString() (Y-m-d)
  • Edm.TimeOfDay->format('H:i:s')

Null values on nullable columns pass through. Already-correct strings round-trip cleanly. Implementation lives in Protocol\Execution\RowCoercion; both EntitySetHandler and EntityHandler apply it.

Migration

No code changes required in consumer PHP. composer update picks up the fix; columns declared as EdmPrimitiveType::DateTimeOffset (or Date / TimeOfDay) start emitting spec-compliant strings automatically.

UI5 frontends should drop two now-obsolete workarounds:

  • targetType: 'any' on bindings against temporal columns — the default type parsers now work correctly.
  • Custom formatters that re-parse MySQL-style strings — the wire is already RFC 3339.

grep -rn "targetType.*'any'" <ui5-source-roots> is a reasonable starting survey.