Skip to content

Harden the date engine: clamp events, cache the grid, follow day changes and locale weekends - #150

Merged
mmick66 merged 1 commit into
masterfrom
harden-date-engine
Sep 8, 2026
Merged

mmick66 merged 1 commit into
masterfrom
harden-date-engine

Conversation

@mmick66

@mmick66 mmick66 commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Summary

A review of the date engine after 2.0.0: MonthGrid, event bucketing, the data source cache and calendar handling. Each suspected edge case was written as a test first and run against the unchanged code, so every finding below is confirmed, not theoretical. One commit.

Confirmed and fixed

  • Open-ended events blocked the main thread. Bucketing walked every day of an event's span. An event ending in the year 4000 took 13 seconds; long recurring or open-ended EventKit events would do the same. Bucketing is clamped to the displayed months.
  • The data source was asked ~150 times per reload. Every cell re-queried startDate() and endDate(). The grid and the today index path are cached and refreshed once per reload; reloadData() refreshes them.
  • The today marker went stale at midnight. The view now reloads on NSCalendarDayChanged and UIApplication.significantTimeChangeNotification, which also covers time zone changes.
  • Weekends ignored the style's locale. A Calendar(identifier:) without a locale falls back to Saturday and Sunday, so an ar_SA calendar marked Sunday instead of Friday. CalendarView.calendar carries style.locale when the calendar has none.

Checked and already correct

  • Every day of a DST year (Europe/Athens 2024) round-trips through an index path, including the first and last minute of each day.
  • Chile's 8 September 2024, which starts at 01:00 because DST begins at midnight, matches startOfDay; selection on it works.
  • Hebrew leap years with 13 months round-trip.

Test plan

  • xcodebuild -scheme KDCalendar-Package -destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=26.5' test — 72 tests in 4 suites pass, including the new EngineTests
  • Example app builds and loads real system events on the iPhone 17 Pro (iOS 26.5) simulator
  • xcodebuild docbuild clean
  • xcrun swift-format lint --strict --recursive Sources Tests Example/KDCalendarDemo clean

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ubk2MsmduPdDLM7FZXFU8C

A review of MonthGrid, event bucketing and the data source cache, each
suspected edge case pinned as a test first. Two DST cases and Hebrew leap
years already passed; four did not.

- Event bucketing is clamped to the displayed months. An event ending in
  the year 4000 looped day by day for 13 seconds on the main thread;
  open-ended system events would have done the same.
- The data source is asked for its range once per reload instead of on
  every cell access (about 150 calls per reload before). The grid and the
  today index path are cached between reloads; reloadData refreshes them.
- The today marker follows midnight and clock or time zone changes: the
  view reloads on NSCalendarDayChanged and significantTimeChangeNotification.
- CalendarView.calendar carries style.locale when style.calendar has no
  locale of its own, so weekends follow the locale (Friday and Saturday
  for ar_SA) instead of falling back to Saturday and Sunday.
- New EngineTests suite: every day of a DST year round-trips with its
  first and last minute, Chile's day that starts at 01:00 matches
  startOfDay, far-off events are clamped, the data source is asked at most
  a handful of times per reload, locale weekends, 13-month Hebrew years,
  and the today marker after a day change. 72 tests in four suites.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ubk2MsmduPdDLM7FZXFU8C
@mmick66
mmick66 merged commit fd71ae0 into master Sep 8, 2026
2 checks passed
@mmick66
mmick66 deleted the harden-date-engine branch September 8, 2026 10:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant