# ICS Timezone Shifter

Rewrite DTSTART and DTEND values in an .ics calendar from one timezone to another, preserving all-day events and emitting TZID, UTC, or floating output.

## Run it

- **CLI:** `gizza tool ics-timezone-shifter "BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:demo@example
DTSTART:20240310T140000Z
DTEND:20240310T150000Z
SUMMARY:Standup
END:VEVENT
END:VCALENDAR"`
- **Web:** https://gizza.ai/tools/ics-timezone-shifter/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/ics-timezone-shifter/tool.json

## Inputs

- `input` — .ics calendar text _(field)_
- `from` — Source timezone for floating times _(field)_
- `to` — Target timezone _(field)_
- `mode` — Mode _(field)_
- `write_as` — Write output times as _(field)_
- `include_vtimezone` — Include generated VTIMEZONE when writing TZID values _(field)_

## Output

- Shifted .ics (text)

## Query parameters

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

- `input` — .ics calendar text
- `from` — Source timezone for floating times
- `to` — Target timezone
- `mode` — Mode
- `write_as` — Write output times as
- `include_vtimezone` — Include generated VTIMEZONE when writing TZID values

Example: `https://gizza.ai/tools/ics-timezone-shifter/?input=BEGIN%3AVCALENDAR%0AVERSION%3A2.0%0ABEGIN%3AVEVENT%0AUID%3Ademo%40example%0ADTSTART%3A20240310T140000Z%0ADTEND%3A20240310T150000Z%0ASUMMARY%3AStandup%0AEND%3AVEVENT%0AEND%3AVCALENDAR&from=America%2FNew_York&to=Europe%2FBerlin&mode=convert&write_as=tzid&include_vtimezone=true`

---

## About this tool

Calendar exports are easy to get almost right and still be unusable. A meeting written as `DTSTART:20240710T090000` means "9 AM somewhere" until the importer decides what timezone "somewhere" is. A meeting written as `DTSTART;TZID=America/New_York:20240710T090000` has a zone, but it may need to become Berlin time for another system. This tool rewrites the timed parts of an iCalendar file so the result imports with the timezone model you choose.

A default conversion preserves the instant in time and expresses it in the target timezone. For example:

```
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:demo@example
DTSTART:20240310T140000Z
DTEND:20240310T150000Z
SUMMARY:Standup
END:VEVENT
END:VCALENDAR
```

with target `Europe/Berlin` becomes a calendar with a generated `VTIMEZONE` and event times like:

```
DTSTART;TZID=Europe/Berlin:20240310T150000
DTEND;TZID=Europe/Berlin:20240310T160000
```

Use **Source timezone for floating times** when the input values have no `Z` and no `TZID`. Existing `TZID` parameters in the file are trusted in convert mode. Use **Relabel** mode when the wall-clock digits are already correct but the zone marker is wrong: `09:00Z` can become `09:00 America/New_York` rather than the equivalent UTC instant.

**Write output times as** controls the format of the result. `TZID` writes target-zone local values and can include a fresh `VTIMEZONE`. `UTC` writes `...Z` values and omits timezone definitions. `Floating` writes local wall-clock values with no zone marker, for importers that assign the zone outside the file.

Limits and edge cases:

- Up to 5,000 `VEVENT` blocks per run.
- Timed `DTSTART`, `DTEND`, `DUE`, `RECURRENCE-ID`, `EXDATE`, `RDATE`, and `RRULE` `UNTIL` values are rewritten.
- All-day `VALUE=DATE` events never move.
- `DTSTAMP`, `CREATED`, `LAST-MODIFIED`, alarms, attendees, descriptions, summaries, and unknown properties pass through.
- Existing `VTIMEZONE` blocks are removed before an optional fresh target-zone block is inserted.
- Ambiguous fall-back times use the earlier occurrence; spring-forward gap times roll forward one hour.
- Lines are unfolded before processing and folded back to 75-octet iCalendar lines.

## FAQ

<details>
<summary>What is the difference between convert and relabel?</summary>

**Convert** preserves the real instant. If a meeting is `20240310T140000Z`, Berlin output is `20240310T150000` because 14:00 UTC is 15:00 in Berlin on that date. **Relabel** preserves the written clock digits and changes what timezone they mean. Use relabel only when an export says the wrong timezone but the local meeting time is already what you want.

</details>

<details>
<summary>Will all-day events shift to the previous or next day?</summary>

No. All-day iCalendar values are written as `VALUE=DATE`, not as instants. The tool leaves those values unchanged, so a holiday or vacation day does not slide across a date boundary just because the target timezone is far away.

</details>

<details>
<summary>Why does the tool replace VTIMEZONE blocks?</summary>

Once every timed value is rewritten into the target zone, the old timezone definitions are stale. The tool removes them and, when writing `TZID` output, inserts one target-zone `VTIMEZONE` built from the IANA timezone data used by `chrono-tz`. If your importer already has its own timezone database, turn off the generated block.

</details>

<details>
<summary>Does this modify recurrence rules?</summary>

It keeps recurrence rules intact and only rewrites an `UNTIL` date-time when one is present. Date-only `UNTIL` values are left alone. Exception date lists (`EXDATE`) and recurrence date lists (`RDATE`) are shifted along with event starts and ends.

</details>

<details>
<summary>Can I paste only a VEVENT instead of a full VCALENDAR?</summary>

Yes. Bare event blocks are accepted and wrapped in a minimal `VCALENDAR` so the output imports cleanly. A full `.ics` file is preferred when you want calendar-level fields such as `VERSION`, `PRODID`, or `X-WR-TIMEZONE` preserved.

</details>

## Related tools

- [ICS Agenda View](https://gizza.ai/tools/ics-agenda-view/): Paste an iCalendar .ics file to render a day-by-day agenda, expand common recurrences, convert timezones, and list free gaps between meetings.
- [Age Calculator](https://gizza.ai/tools/age-calculator/): Calculate your exact age from your date of birth — years, months and days, next birthday countdown and total days lived. Free, private, in-browser.
- [Current UTC Time](https://gizza.ai/tools/clock/): See the current UTC date and time, updating live in your browser. No sign-up, runs offline.
- [Cron Next Run Times](https://gizza.ai/tools/cron-next-runs/): Cron expression parser and next-run calculator — see upcoming run times in UTC with plain-English schedules, free and entirely in your browser.
- [Date Difference Calculator](https://gizza.ai/tools/date-diff/): Calculate the exact duration between two dates: years, months, days, hours, minutes and seconds, with leap years handled. Free, private, in-browser.
