# Calendar Free/Busy Overlap

Paste two .ics calendars and list the time slots where both are free — working hours, minimum meeting length, timezones and DST handled. Free and in-browser.

## Run it

- **CLI:** `gizza tool calendar-freebusy-overlap "BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
DTSTART:20260720T090000Z
DTEND:20260720T100000Z
SUMMARY:Standup
END:VEVENT
END:VCALENDAR" 'calendar_b=BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
DTSTART:20260720T120000Z
DTEND:20260720T130000Z
SUMMARY:Lunch sync
END:VEVENT
END:VCALENDAR'`
- **Web:** https://gizza.ai/tools/calendar-freebusy-overlap/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/calendar-freebusy-overlap/tool.json

## Inputs

- `calendar_a` — Calendar A (.ics text) _(field)_
- `calendar_b` — Calendar B (.ics text) _(field)_
- `start_date` — First day to scan _(field)_
- `days` — Days to scan _(field)_
- `day_start` — Earliest time (working hours start) _(field)_
- `day_end` — Latest time (working hours end) _(field)_
- `min_minutes` — Minimum slot length (minutes) _(field)_
- `timezone` — Timezone (IANA name) _(field)_
- `weekends` — Include weekends _(field)_
- `output` — Output format _(field)_

## Output

- Common free slots (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `calendar_a` — Calendar A (.ics text)
- `calendar_b` — Calendar B (.ics text)
- `start_date` — First day to scan
- `days` — Days to scan
- `day_start` — Earliest time (working hours start)
- `day_end` — Latest time (working hours end)
- `min_minutes` — Minimum slot length (minutes)
- `timezone` — Timezone (IANA name)
- `weekends` — Include weekends
- `output` — Output format

Example: `https://gizza.ai/tools/calendar-freebusy-overlap/?calendar_a=BEGIN%3AVCALENDAR%0AVERSION%3A2.0%0ABEGIN%3AVEVENT%0ADTSTART%3A20260720T090000Z%0ADTEND%3A20260720T100000Z%0ASUMMARY%3AStandup%0AEND%3AVEVENT%0AEND%3AVCALENDAR&calendar_b=BEGIN%3AVCALENDAR%0AVERSION%3A2.0%0ABEGIN%3AVEVENT%0ADTSTART%3A20260720T120000Z%0ADTEND%3A20260720T130000Z%0ASUMMARY%3ALunch%20sync%0AEND%3AVEVENT%0AEND%3AVCALENDAR&start_date=2026-07-20&days=7&day_start=09%3A00&day_end=17%3A00&min_minutes=30&timezone=Europe%2FBerlin&weekends=true&output=text`

---

## Find the free time two calendars share

Trying to schedule with someone whose calendar you can't see live? Ask them for an
iCalendar export, paste both files above, and this tool lists every window where **both**
of you are free — restricted to working hours, on the days you choose, at least as long
as the meeting you need. Everything runs locally in your browser: the calendars never
leave your machine.

It reads standard **.ics exports** from Google Calendar (Settings → Import & export →
Export), Outlook (Save calendar), Apple Calendar (File → Export), Fastmail, Proton and
any other RFC 5545 producer. Busy time is taken from `VEVENT`s — including recurring
events — and from `VFREEBUSY` busy periods, so an availability-only export works too.
Events marked cancelled or free (`STATUS:CANCELLED`, `TRANSP:TRANSPARENT`) don't block
time.

## Worked example

Calendar A has a standup on Monday 2026-07-20 from 09:00–10:00 UTC; calendar B has a
lunch sync from 12:00–13:00 UTC. Scanning that single day between 09:00 and 17:00 with a
30-minute minimum returns:

```
Common free time — 2026-07-20 to 2026-07-20 · Mon–Fri 09:00–17:00 · UTC · ≥30m
Calendar A: 1 busy interval · Calendar B: 1 busy interval

Mon 2026-07-20  10:00–12:00  (2h)
Mon 2026-07-20  13:00–17:00  (4h)

2 free slots · 6h total
```

Pick the **JSON** output for machine-readable slots with ISO 8601 timestamps, or the
**iCalendar (.ics)** output to get the shared availability back as an RFC 5545
`VFREEBUSY` calendar (one `FREEBUSY;FBTYPE=FREE` period per slot) that other tools can
import.

## What's supported, and the limits

- **Recurring events:** `RRULE` with `FREQ=DAILY/WEEKLY/MONTHLY/YEARLY`, `INTERVAL`,
  `COUNT`, `UNTIL`, weekly `BYDAY` lists (e.g. `MO,WE,FR`), monthly ordinal `BYDAY`
  (e.g. `3MO` = third Monday), a single `BYMONTHDAY`, and `EXDATE` exceptions. Rules
  outside this subset (e.g. `BYSETPOS`, hourly frequencies) block only their first
  occurrence, and the result says so in a note.
- **Timezones:** event `TZID`s are resolved against the full IANA database (DST-correct),
  and the most common Windows/Outlook zone names ("Eastern Standard Time", "W. Europe
  Standard Time", …) are mapped automatically. Unknown TZIDs fall back to your selected
  timezone, with a note in the result.
- **Moved instances:** a rescheduled occurrence of a recurring meeting
  (`RECURRENCE-ID`) counts as extra busy time while the original slot also stays
  blocked — deliberately conservative, so a suggested slot is never secretly busy.
- **Caps:** each calendar up to 1 MiB of text; the scan range is 1–60 days; the minimum
  slot length is 5–720 minutes; up to 20,000 busy intervals after recurrence expansion.
- All-day events block the whole day; multi-day events block every day they span.

## FAQ

<details>
<summary>How do I get the .ics text of a calendar?</summary>

In Google Calendar open Settings → Import & export → Export, unzip the download and open
the `.ics` file in any text editor. In Outlook use File → Save Calendar (choose the date
range and full details or free/busy). On macOS/iOS Calendar use File → Export → Export.
Then copy the file's text and paste it here. If someone shares a `.ifb` free/busy file,
that works too — `VFREEBUSY` periods are understood.

</details>

<details>
<summary>Are recurring meetings like a weekly standup handled?</summary>

Yes. Daily, weekly, monthly and yearly `RRULE`s are expanded inside the scan range,
including `INTERVAL` (every 2 weeks), `COUNT`/`UNTIL` bounds, weekly `BYDAY` day lists,
monthly patterns like "third Monday" (`BYDAY=3MO`) and cancelled single occurrences
(`EXDATE`). Exotic rules (`BYSETPOS`, `BYWEEKNO`, hourly repeats) are outside the
supported subset: such an event blocks only its first occurrence and the result appends
a note, so nothing is dropped silently.

</details>

<details>
<summary>What if the two calendars are in different timezones?</summary>

That's fine — each event carries its own timezone (`TZID` or UTC `Z` times), and every
event is converted to the timezone you select before computing overlap, with daylight
saving handled by the IANA database. The working-hours window and the result times are
expressed in your selected timezone. Common Windows zone names used by Outlook exports
are mapped to IANA zones automatically; an unknown TZID falls back to your selected
zone and the result tells you.

</details>

<details>
<summary>Why is a slot shown when one calendar looks busy (or the other way around)?</summary>

Check three things. First, events marked free (`TRANSP:TRANSPARENT`, how "Free" shows in
Outlook) and cancelled events deliberately don't block time. Second, make sure the
selected timezone is the one you expect — the slot list is expressed in it, not in the
calendar's zone. Third, a gap shorter than the minimum slot length is hidden; lower
"Minimum slot length" to see it. In the other direction, a moved instance of a recurring
meeting keeps its original slot blocked too (conservative on purpose).

</details>

<details>
<summary>Is my calendar data uploaded anywhere?</summary>

No. The page is a static site running a WebAssembly module; parsing and the overlap
computation happen entirely in your browser. Your `.ics` text is never sent to a server,
which is exactly why this tool asks you to paste the export instead of a calendar URL.

</details>

## Related tools

- [Extract Action Items from Meeting Notes](https://gizza.ai/tools/action-item-extractor/): Extract action items, owners, and decisions from meeting notes or daily notes with deterministic rules. Markdown checklist or JSON, private in-browser.
- [Amazon Order Analyzer](https://gizza.ai/tools/amazon-order-analyzer/): Paste an Amazon order-history CSV export to summarize total spend by month, top items, and category breakdowns. Browser-only, private, with Markdown or JSON output.
- [Base Decoder](https://gizza.ai/tools/base-decoder/): Auto-detect and decode Base16, Base32, Base45, Base58, Base64, and Base85 text, including nested layers, locally in your browser.
- [Budget Planner](https://gizza.ai/tools/budget-planner/): Plan a monthly budget from take-home pay: 50/30/20 needs/wants/savings targets with custom splits, or a zero-based plan showing what's left to allocate.
- [Preview a Bulk File Rename](https://gizza.ai/tools/bulk-file-renamer/): Preview old-to-new filename mappings with find/replace, regex, numbering, case conversion, prefix/suffix, and collision warnings.
