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

tz: add Offset::round and fix Africa/Monrovia parsing #234

Merged
merged 2 commits into from
Feb 1, 2025

Conversation

BurntSushi
Copy link
Owner

This adds a new Offset::round API in order to support fixing #231.

Namely, previously, we would fail to parse zoned datetimes
like 1969-12-31T23:15:30-00:45[Africa/Monrovia] because
Africa/Monrovia's offset at the time was -00:44:30, which doesn't
match -00:45:00. This in turn caused an error because Jiff's default
behavior is to reject parsed datetimes whose offset doesn't match a
valid offset in the corresponding time zone.

However, in this case, we want to accept it. What it comes down to
is that RFC 3339 and RFC 9557 do not support fractional minutes in
the offset. (I wonder why they flubbed that one.) So in order to
be compatible with existing implementations, Jiff serializes zoned
datetimes with fractional minutes by rounding to the nearest minute.
Hence why you might see -00:45. But this in turn means Jiff wouldn't
be able to parse a zoned datetime that itself serialized. Which is sad.

So in learning from Temporal here, we permit offsets from tzdb that
have fractional minutes to be rounded to the nearest minute before
being compared with the parsed offset. In this case, -00:44:30 gets
rounded to -00:45 and thus compares equal with the parsed offset.

Note though that the offset of the parsed zoned datetime is still,
correctly, -00:44:30. It only becomes -00:45 when serializing via
the Temporal datetime printer. (One can print an offset with second
precision via the %z or %:z strftime conversion specifiers.)

Ref tc39/proposal-temporal#3079
Fixes #231, Closes #233

This is to help support `Offset` equality that rounds to the nearest
minute. It's also pretty easy to add since we can just reuse
`SignedDuration::round`.

We also add `TryFrom<SignedDuration> for Offset` and
`From<Offset> for SignedDuration`.

Closes #233
This new routine is like `resolve`, but permits callers to control
how and when two offsets are considered equal. This is then in turn
used by our Temporal datetime parser to permit parsing of offsets
that have been rounded to the nearest minute without rejecting them
for being unequal.

Fixes #231
@BurntSushi BurntSushi force-pushed the ag/fix-offset-comparison branch from bb325b7 to dceb890 Compare February 1, 2025 16:14
@BurntSushi BurntSushi merged commit 85e2b5a into master Feb 1, 2025
20 checks passed
@BurntSushi BurntSushi deleted the ag/fix-offset-comparison branch February 1, 2025 17:41
BurntSushi added a commit that referenced this pull request Feb 1, 2025
I meant to include this in #234, but it slipped my notice.

Basically, if two offsets compare equal as-is, then it should always
return true. Before this, if our parsed offset was `-00:44:30` and the
time zone offset was `-00:44:30`, we were returning them as not equal
because we skipped to rounding the latter to the nearest minute.

I fixed this in the parser implementation but forgot to fix it in the
doc example. That's what this commit does.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant