RFC 3339 wire coercion for temporal types
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.TimeOfDaywire format. Row-emission path now coerces declared temporal columns to OData v4 / RFC 3339 strings before JSON encoding. Previously, MySQLDATETIME/DATE/TIMEvalues (e.g.2026-05-05 12:34:56) passed through unchanged — invalid per the spec, returningNaNfromDate.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.