Possible bug in calendar:rfc3339_to_system_time/2 with fractional seconds before the unix epoch?

Hello friends.

Ryan Moore has been working on RFC3339 timestamp parsing for Gleam and found a behaviour in calendar:rfc3339_to_system_time/2 that we don’t understand, and I’m worried it may be a bug. Our conversation can be read here on GitHub, and I’ll summarise here.

In Erlang, for negative timestamps, the fractional part of the timestamp appears to be representing a fraction into the previous second.

8> calendar:rfc3339_to_system_time("1969-12-31T23:59:58.5Z", [{unit, millisecond}]).
-2500
9> calendar:rfc3339_to_system_time("1969-12-31T23:59:59.5Z", [{unit, millisecond}]).
-1500
10> calendar:rfc3339_to_system_time("1970-01-01T00:00:00.5Z", [{unit, millisecond}]).
500
11> calendar:rfc3339_to_system_time("1970-01-01T00:00:01.5Z", [{unit, millisecond}]).
1500

This is different from the other languages which Ryan tested with: JavaScript, Rust, Python, Ruby, Java, and OCaml. They treat the fractional part of the timestamp as being a traction into the current second.

> d = new Date("1969-12-31T23:59:58.5Z"); d.getTime()
-1500
> d = new Date("1969-12-31T23:59:59.5Z"); d.getTime()
-500
> d = new Date("1970-01-01T00:00:00.5Z"); d.getTime()
500
> d = new Date("1970-01-01T00:00:01.5Z"); d.getTime()
1500

Is this our misunderstanding calendar:rfc3339_to_system_time/2, is it a bug, or something else?

Thanks,
Louis

1 Like

Looks very much like a bug…

17> calendar:system_time_to_rfc3339(-500, [{unit,millisecond}, {offset, "Z"}]).
"1970-01-01T00:00:00.500Z"
18> calendar:system_time_to_rfc3339(500, [{unit,millisecond}, {offset, "Z"}]).
"1970-01-01T00:00:00.500Z"
...
23> calendar:system_time_to_rfc3339(-999, [{unit,millisecond}, {offset, "Z"}]).
"1970-01-01T00:00:00.999Z"
24> calendar:system_time_to_rfc3339(-1000, [{unit,millisecond}, {offset, "Z"}]).
"1969-12-31T23:59:59.000Z"
25> calendar:system_time_to_rfc3339(-1001, [{unit,millisecond}, {offset, "Z"}]).
"1969-12-31T23:59:59.001Z"

1 Like

I agree, this seems like a bug. Please open an issue on github.

2 Likes

Will do. Thanks folks