Skip to content

Add support for "date" and "date-time" with fractional seconds decoding in accordance with RFC 3339 #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

abacusgiesinger
Copy link

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 as partial-time time-offset. And partial-time is defined as time-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 the ISO8601DateFormatter 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] if dateString 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...

  • "2023-05-21T11:22:33.123456+02:00"
  • "2023-05-21T11:22:33.123Z"
  • "2023-06-01"

...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.)

@abacusgiesinger
Copy link
Author

Both issues are handled:

"format: date": apple/swift-openapi-generator#137
fractional seconds: apple/swift-openapi-generator#84

I believe this change makes little sense with the provided solutions and should therefore be closed.

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.

2 participants