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

Stub out tzdb support to unblock Now and ZonedDateTime #99

Merged
merged 10 commits into from
Oct 31, 2024

Conversation

nekevss
Copy link
Member

@nekevss nekevss commented Oct 25, 2024

And thus begins the Great Time Zone / ZonedDateTime implementation. 😅

This stubs out tzdb support by relying solely on the user's zoneinfo files, and should allow us to move forward with implementing and testing ZonedDateTime without being blocked by a proper tzdb provider for Boa.

This PR implements:

  • Now builtin
  • FsTzdbProvider stub
  • Some ZonedDateTime APIs along with experimental, non-engine focused APIs.

Things of note that are not in this PR:

  • Handling POSIX's proleptic tz format and non-fat version of the TZDB.
  • Any thing zoneinfo / zic related.
  • Tests for more time zone edge cases
  • Many ZonedDateTime methods and abstract ops
  • Windows Support

Let me know what you think :)

@nekevss nekevss marked this pull request as ready for review October 25, 2024 21:37
Copy link
Member

@jasonwilliams jasonwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!
Good start, nice to have a way forward which will unblock us for now


use crate::{components::tz::TzProvider, iso::IsoDateTime, TemporalError, TemporalResult};

const ZONEINFO_DIR: &str = "/usr/share/zoneinfo/";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is why you have the non-windows flags everywhere else, is there even a window equivalent file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there's not really a windows equivalent, so we will need to package tzdb for windows.

That's where we may be able to use jiff_tzdb as an intermediate step, but we would need to add steps for resolving from the POSIX tz string as jiff is compiled in the "slim" format of tzdb while linux and macos are compiled in "fat"

Cargo.toml Outdated

tzif = "0.2.3"
iana-time-zone = "0.1.61"
once_cell = "1.20.2"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this being used? Also I think once_cell is built into the standard library now, the crate shouldn't be needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Forgot to remove it when I moved to std.

Copy link
Member

@jedel1043 jedel1043 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for all your work! I'm really excited to start playing with the timezone pieces.

Since this is still experimental, we can delay the resolution of my timezone related comments by opening an issue to address them if it would block merging this by a considerable amount.

src/components/tz.rs Outdated Show resolved Hide resolved
src/tzdb.rs Outdated
Comment on lines 174 to 206
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small cleanup

Suggested change
}
}
if let Some(tzif) = self.cache.get(identifier) {
return Ok(identifier);
}
let tzif = Tzif::read_tzif(identifier)?;
Ok(self.cache.entry(identifier.into()).or_insert(tzif))

Copy link
Member Author

@nekevss nekevss Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, I really like this solution, but it looks like it has a lifetime issue around self.cache.get having an immutable borrow and self.cache.entry borrowing it mutably.

Granted that's probably fixed after adjusting for moving TzProvider to &self

src/tzdb.rs Outdated Show resolved Hide resolved
src/tzdb.rs Outdated Show resolved Hide resolved
src/tzdb.rs Outdated
let record_minus_one = get_local_record(data_block, estimated_idx - 1);

// Potential shift bugs with odd historical transitions?
let shift_window = usize::from((record.utoff + record_minus_one.utoff).0.signum() >= 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me a bit of time to understand that this is just checking if the sum of offsets is positive, so maybe just do that?

Suggested change
let shift_window = usize::from((record.utoff + record_minus_one.utoff).0.signum() >= 0);
let shift_window = usize::from(record.utoff + record_minus_one.utoff >= Seconds(0))

src/tzdb.rs Outdated
.expect("binary_search validates that data_block2 exists.");

let estimated_idx = match b_search_result {
Ok(idx) => idx,
Copy link
Member

@jedel1043 jedel1043 Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just return the timezone data when the binary search finds a corresponding entry (Ok(idx))?

src/tzdb.rs Outdated
Comment on lines 129 to 133
let record = get_local_record(data_block, estimated_idx);
let record_minus_one = get_local_record(data_block, estimated_idx - 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this handles indexing to the transition table correctly. What if the estimated index is one past the end of the table, because the epoch is bigger than any of the transition times?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if I remember correctly, I think there may have been a bug here, but it should also be solved by #100. If the value is past the transition times, then we need to use the POSIX tz string to resolve.

Ideally, at least the way I am understanding the behavior, we should return the first index if the seconds < transition_times[0]. if the value is greater than transition_times[n-1], then the POSIX tz string should be used to resolve the time zone.

src/tzdb.rs Show resolved Hide resolved
src/tzdb.rs Outdated Show resolved Hide resolved
Copy link
Member

@jedel1043 jedel1043 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

@nekevss nekevss merged commit 0686135 into main Oct 31, 2024
5 checks passed
nekevss added a commit that referenced this pull request Nov 3, 2024
Builds on #99.

This PR adds resolving the POSIX tz string and should allow handling
time zones on Windows via `jiff_tzdb` as a source, which should make the
stub overall somewhat stable overall until a different solution can be
put into place.
@nekevss nekevss added the C-enhancement New feature or request label Nov 3, 2024
jedel1043 pushed a commit that referenced this pull request Nov 3, 2024
Re: title, depends on #99 and #100

This PR implements `ZonedDateTime`'s add and subtract methods along with
related `TimeZone` operations that were needed.

There is also one test to verify the results based off test262.
@nekevss nekevss deleted the stub-tzdb-support branch November 5, 2024 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants