We are going to try and break `test` apart in order to speed up CI
builds. I don't want to pollute the root project directory with more
random test scripts, so let's tuck them away for now.
This isn't quite done, but it does parse TZif and emits the correct
Jiff code to construct a `TimeZone` in a const context.
The main thing missing here is a fair bit of polish and a change
to the TimeZone internals to actually support this method of
construction in core-only environments without increasing the size
of `TimeZone` (i.e., pointer tagging).
This adds new APIs for iterating over the preceding and following time
zone transitions from a particular point in time.
The hard work was something I actually did a bit ago, but I never
exposed, since I didn't want to figure out the API details. There's
actually a fair bit of information we can expose (timestamp, offset,
abbreviation and whether DST is active), so we introduce a new type that
wraps this all up.
Closes#144
There are a few main downsides to core-only support:
1. The error messages produced by Jiff are now awful.
2. Time zone integration is basically gone. All you get are fixed offset
time zones. Neither POSIX time zones nor IANA time zones are
supported.
3. The sizes of some types (e.g., `TimeZone` and `Zoned`) are now bigger
than they are when `alloc` is enabled.
It is possible (1) could be mitigated somewhat, but not entirely. One
way they could be improved is by using more structured error types
instead of strings at the point where the error occurs. When using
strings, some kind of interpolation is needed to convert it to a heap
allocated `String`. But if we used structured error types, we wouldn't
need this heap allocation in the vast majority of cases. However,
doing this is a major pain. Additionally, a significant component
of Jiff's error messages is its chaining, which enables the easy
contextualization of errors. I don't see how to do this in core-only
contexts. In any case, I could maybe be convinced to switch to more
structured errors, but I would need real users of Jiff in core-only mode
to convince me to spend that effort and maintenance headache.
As for (2), time zone integration could be improved. But again, I'd like
to see use cases before digging into this in order to avoid exposing the
wrong API. In particular, POSIX time zones do actually work fine in
core-only contexts, but I've disabled them for now because they greatly
increase the size of a `TimeZone`. There are, I think, ways of shrinking
it without changing the API, but it would be a lot of effort. However,
IANA time zone support is a somewhat different beast, and that requires
some careful thought and real use cases to guide its development.
And for (3), I'm not really sure how to get around inflating the size of
types. My suspicion is that this is really unavoidable, and that it
probably makes using things like `Zoned` in a core-only context
untenable. For core-only, my guess is that they will want an `Unzoned`
type that is like `Zoned`, but doesn't carry a time zone and instead
requires callers to pass in a `&TimeZone` for every API that needs it.
But again, this is a lot of effort to build and I don't want to do it
unless there are compelling use cases for it.
Otherwise, here are some additional small changes that fell out of this
work:
* `Zoned`'s API now includes `FromStr` and `intz` in no-std mode.
This makes it more consistent with other APIs that offer `intz`. I
believe this was a holdover from when `jiff::tz::db()` was itself only
available when `std` was enabled. But I had changed to a model where it
was always available, but, e.g., the time zone database was empty. I
updated routines like `Timestamp::intz` to always be available, but
apparently didn't do it for `Zoned`.
* The docs now make it clear that you need `std` to use the global time
zone database. And explicitly mention that even without `std`, but so
long as `alloc` is enabled, you can still use a `TimeZoneDatabase` with
a bundled copy of the IANA time zone database.
I originally tried to do this work in a commit-by-commit manner, but it
got way too messy. So I just piled everything into one commit.
I was lured into a false sense of confidence with CI testing. Because
tests unconditionally enable `std`, this
cargo test --lib --no-default-features --features alloc
doesn't actually fail when there is an errant `std` reference. But this
does:
cargo build --no-default-features --features alloc
We fix our `test` script to catch this case and also fix the build
errors.
Fixes#108