Repository navigation
Conversation
…e-time The OpenAPI Format Registry defines date-time-local as an RFC 3339 date-time without a time zone. It fell through to String, and under datetime = :zoned a date-time with no offset decoded as UTC. - Under :zoned, date-time-local maps to Dates.DateTime, a wall clock. Generated :zoned models encode through _encode_zoned, which writes a DateTime with no offset. Under :utc, date-time-local stays String, because DateTime already means a UTC instant there. - The ZonedDateTime decoder requires Z or an offset, as RFC 3339 date-time does. The regex ends with \z, so a trailing newline fails. - CONTRACT_VERSION is 5: generated code imports _encode_zoned.
This was referenced Oct 28, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The OpenAPI Format Registry
defines
date-time-localas an RFC 3339 date-time without a time zone. OpenAPI.jl did notmap it, so the field became a
String. Underdatetime = :zoned, adate-timewith nooffset decoded as UTC, which RFC 3339 does not allow.
This PR replaces #134 (closed), which proposed a custom
datetime = :as_writtenmode.It uses the registry format instead, so the schema states the form of each timestamp.
Behavior
datetime = :utc(default)datetime = :zoneddate-timeDates.DateTime, offset normalized to UTC (unchanged)ZonedDateTime;Zor an offset is now requireddate-time-localString(unchanged)Dates.DateTime, a wall clock with no offsetanyOfof bothUnder
:utc,Dates.DateTimealready means a UTC instant, sodate-time-localstays aStringthere. Under:zoned,date-timeis aZonedDateTime, so aDates.DateTimecan only mean the wall clock.
Changes
src/planning.jl:format: date-time-localmaps through_local_datetime_type!,dispatched on
Val(datetime).src/client.jl,src/servergen.jl:_emit_modeltakes anencodekeyword. A:zonedmodule encodes model fields, aliases, union values and additional properties through
_encode_zoned.:utcoutput does not change.src/runtime.jl:_encode_zoned(::Dates.DateTime)writesyyyy-mm-ddTHH:MM:SS.ssswith no offset, and recurses into vectors, tuples, dicts and named tuples. Any other
value goes to
_encode.ext/OpenAPITimeZonesExt.jl: theZonedDateTimedecoder requiresZor an offset.Its regex ends with
\z, so a trailing newline is rejected. PCRE$matches beforeone.
CONTRACT_VERSIONis 5, because generated code imports_encode_zoned. Contract 3 and4 modules still load.
clients.md,models.md,artifacts.md,servers.md, and theclientdocstring.
Breaking change for
:zonedusersA
:zonedmodule rejects adate-timevalue with no offset. Before, it read the value asUTC. The existing test that pinned that behavior now asserts a
DecodeError. A producerthat writes zoneless values should declare them
date-time-local.Limits
A
date-time-localvalue sent directly as a query, header or cookie parameter, or as atop-level request body, still goes through
_encode/_scalar, which addZ. Onlymodel values use
_encode_zoned.The release that carries contract 5 needs a version bump. I left that to you.
Tests
test/runtime.jlhas a new test set, "date-time-local is a wall clock under datetime =:zoned". It covers:
:utckeepsString;:zonedfield types for a required, an array and ananyOffield;anyOfbranch selection by schemapattern;The
:zonedtest set now asserts that a zoneless value and a trailing newline arerejected.
test/generated_contract.jlmoves its tripwire to contract 5 and checks thatcontracts 3, 4 and 5 load.
julia --project=. -e 'using Pkg; Pkg.test()': "OpenAPI tests passed", 1442 passes, 0failures, 0 errors.
generated runtime units: 392 of 392.