Skip to content
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

to_rfc3339 can generate invalid RFC 3339 timestamps #7

Open
mooreryan opened this issue Jan 2, 2025 · 3 comments
Open

to_rfc3339 can generate invalid RFC 3339 timestamps #7

mooreryan opened this issue Jan 2, 2025 · 3 comments

Comments

@mooreryan
Copy link

The to_rfc3339 can generate invalid RFC 3339 timestamps. For example:

Timestamp(-9_007_199_254_740_991, 0) |> to_rfc3339(offset_minutes: 0)
// "-285424812-02-20T16:23:29Z"


Timestamp(9_007_199_254_740_991, 0) |> to_rfc3339(0)
// "285428751-11-12T07:36:31Z"

From the RFC 3339:

All dates and times are assumed to be in the "current era", somewhere between 0000AD and 9999AD

Also the grammar doesn't allow for years with more than 4 digits (or negative years).

I'm not really sure what the "correct" behavior here should be (maybe clamping? maybe return a Result(String, _)?)

@lpil
Copy link
Member

lpil commented Jan 2, 2025

This is fine, but we can document that timestamps outside the specified range can be generated.

@mooreryan
Copy link
Author

Here is another example of generating invalid RFC 3339 timestamps. This time it is with a timestamp that is in the normal range.

Test function

pub fn to_rfc3339_9_test() {
  timestamp.from_unix_seconds(-62_167_219_200)
  |> timestamp.to_rfc3339(0)
  |> should.equal("0000-01-01T00:00:00Z")
}

Test result:

  1) gleam/time/timestamp_test.to_rfc3339_9_test
     Values were not equal
     expected: "0000-01-01T00:00:00Z"
          got:   "00-01-01T00:00:00Z"

The previous examples I can understand being okay, since the timestamp is outside of the natural domain of the RFC 3339 formatted timestamps, but this example seems to be a bug: the timestamp is in the accepted range, but the format is off.

The cause is here:

let n = fn(n) { int.to_string(n) |> string.pad_start(2, "0") }

And here:

let out = out <> n(years) <> "-" <> n(months) <> "-" <> n(days)

(This example with the two digit year does appear to conform to the ISO 8601 grammar given in the RFC 3339 appendix, but not to the RFC 3339 grammar.)

@lpil
Copy link
Member

lpil commented Jan 9, 2025

Oops, that's a copy paste fail for me. I remember intending to pad to 4 😄

mooreryan added a commit to mooreryan/time that referenced this issue Jan 9, 2025
mooreryan added a commit to mooreryan/time that referenced this issue Jan 11, 2025
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

No branches or pull requests

2 participants