Add support for "date" and "date-time" with fractional seconds decoding in accordance with RFC 3339 #34
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.
Motivation
The current runtime uses the
ISO8601DateFormatter
provided by Swift to decode properties with the format 'date' and 'date-time'. OpenAPI docs & Swagger docs both mention these formats.The standard mentioned in the docs and in the comments of this runtime is RFC 3339.
According to the Swagger docs, OpenAPI's "date" is RFC 3339's "full-date" and "date-time" has the same name on both ends.
Unfortunately "date" is not supported by this runtime at all and "date-time" only to limited effect. According to RFC 3339, "date-time" is defined as
full-date "T" full-time
.full-time
is defined aspartial-time time-offset
. Andpartial-time
is defined astime-hour ":" time-minute ":" time-second [time-secfrac]
.The date-time decoding in this runtime stops working if the optional
time-secfrac
is included in the String, despite it being part of RFC 3339.This change aims to fix both of this issues and decoding the date strings in accordance with RFC 3339.
Modifications
Before decoding the
dateString
with theISO8601DateFormatter
I am setting certain options depending on the String provided.If the String contains a dot ("."), I am setting the options to
[.withFractionalSeconds, .withInternetDateTime]
to decode it correctly. According to RFC 3339, "fractional seconds" is the only case where a dot will ever be included in the date String, meaning this change will not break any other RFC 3339 date formats.To handle dates without any time, I am setting the options to
[.withFullDate]
ifdateString
matches the following regex:^\d{4}-\d{2}-\d{2}$
.No other format mentioned in RFC 3339 will produce a String with this exact regex.
Therefore these two changes should not influence any current decoding, but improve it to match the RFC 3339 standard.
Result
The following date strings...
...will all be correctly decoded in accordance to the RFC 3339 standard, whereas before, the decoding would fail. The data after the milliseconds gets lost during the decoding, but according to https://stackoverflow.com/a/23685280 this is a problem caused by the DateFormatter itself, and is not trivial to correct.
Test Plan
I have tested this change manually with the different formats listed above. I have also verified, that this doesn't break any current decoding by testing it with "2023-05-21T11:22:33Z" and "2023-05-21T11:22:33+02:00".
In addition to my manual tests, I will update the tests in this project to include the examples I listed above if you believe this change makes sense and should be merged.
Note about encoding different RFC 3339 date formats
This change only fixes the decoding of RFC 3339 date formats, not encoding.
Encoding RFC 3339 date-time with fractional seconds
This one is quite tricky, as it is not apparent from either the OpenAPI file or the Date provided if (or how many) decimals should be included in the date String. You would probably have to be able to pass this somewhere during the request, but this makes little sense in my opinion with my current limited overview over this project. It's probably easier to create a custom
DateTranscoder
instead of including this here to handle this case.Encoding RFC 3339 date
This one however should be possible. In the OpenAPI file "date" and "date-time" are clearly distinguished. Therefore it may make sense to create a second
DateTranscoder
in this project to decode and encode the properties with the "date" format. At the moment I do not possess a good enough grasp of this project to implement this change cleanly, but it may make sense for a future version.This would allow this runtime to decode all possible RFC 3339 formats mentioned by OpenAPI and encode all except for the date-time with fractional seconds.
(If this change was implemented, the "date" decoding I created here using the regex would become redundant.)