Files
jcoffey-dev 21d859aa4c
ci / fork-checks (pull_request) Skipped
ci / build (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 15m7s
Calendar: keep the UTC zone of a series that starts in UTC
A recurring event whose DTSTART is written in UTC ("...Z", as a JMAP
timeZone of Etc/UTC is stored) came back in the zone of the request:
read with America/Phoenix, an 18:00 UTC weekly event said 01:00Z and,
for its occurrences, America/Phoenix. Named-zone and floating series and
one-off events were right.

calcard took a component's start zone from its TZID or the default, and
the server's default is floating, so every instance of a UTC rule was
stored floating and read in the request's zone. The DTSTART's own
offset now wins, as in calcard 0.4. Series already stored floating are
read in their DTSTART's offset when it has one, so no reindex is needed.
Occurrences of a UTC series are labeled Etc/UTC like the base event, and
the base event's utcStart is worked out before the event is taken out of
its data.

Fixes #303.
2026-11-06 13:11:52 -07:00

3.5 KiB

calcard, vendored

The published calcard 0.3.14, taken from crates.io (.crate sha256 c601473ec15a875626bce73db1a1f0fc81e9c949ca25f1463b714947c0a70a1f, the checksum the server's Cargo.lock had for it) under Apache-2.0 OR MIT. INBUXA takes it under MIT. The root Cargo.toml patches it in with [patch.crates-io].

Left out: the top-level resources/ (26 MB of iCalendar, vCard, JSCalendar and JSContact samples) and .github/, which the server never builds, and Cargo.lock, Cargo.toml.orig, .cargo_vcs_info.json and .cargo-ok. The crate's own tests that read resources/ (expand_rrule, parse_ical, parse_vcard, convert_jscalendar, convert_jscontact and remove_component_ids) can't run here; the crate's other tests run from this directory with:

cargo test --offline --target-dir ../../target/calcard-tests -- \
  --skip expand_rrule --skip parse_ical --skip parse_vcard \
  --skip convert_jscalendar --skip convert_jscontact \
  --skip remove_component_ids

Changes

Every changed file carries a Coffey Labs notice in its header.

  • .gitignore: VENDORED.md is tracked (upstream ignores every *.md but the changelog and README).
  • src/datecalc/mod.rs, src/datecalc/rrule_iter.rs, src/datecalc/counter_date.rs, src/icalendar/dates.rs: one expand_dates call has a single work budget for all its recurrence rules (MAX_EXPANSION_WORK, 1,000,000 units, about 50 ms in a release build). Upstream only stops a rule after 100,000 passes that find nothing, counted afresh for every instance and every rule, so a calendar of a few thousand rules that never match (FREQ=MONTHLY;BYMONTH=2;BYMONTHDAY=31), or one sparse rule, took seconds to minutes. A pass over a period costs one unit, a pass that finds nothing one per 16 days it scanned, each candidate a pass looks at without producing it one, and each time skipped while looking for the next BYHOUR/BYMINUTE/BYSECOND match one (DateTimeIter::increment_counted counts those). When the budget runs out, expansion stops: the instances found so far are kept, as when the instance limit is reached, later rules aren't expanded, and the result carries a CalendarErrorType::ExpansionBudgetExhausted error for the component it stopped at. Rules are no longer started once the instance limit is reached (they couldn't add anything). The budget_tests in dates.rs cover it, and rule_expansion_shares_one_budget in crates/groupware fails to build if the server stops using this copy.
  • src/icalendar/dates.rs: a component whose DTSTART carries an offset (DTSTART:20261102T180000Z) has that zone as its start zone. Upstream took the default zone, which the server passes as floating, so every instance of a UTC rule came out floating (one-off events were already right), and the server then read the series in the zone each request asked for. The start_zone_tests in dates.rs cover it. calcard 0.4 makes the same change.

Updating

When the server's Cargo.lock moves calcard to a new version, Cargo stops using this copy and only warns that the patch went unused, so check Cargo.lock has no calcard entry with a source line. Re-vendor the new version from ~/.cargo/registry/src/*/calcard-*, dropping the top-level resources/ and .github/, Cargo.lock, Cargo.toml.orig, .cargo_vcs_info.json and .cargo-ok (rsync --exclude /resources --exclude /.github ...), repeat the changes above, and update the version here and in the root Cargo.toml comment.