Title, location, date and time, time zone, repeat, invitees, alerts, and notes — then download the .ics file or open it straight in your calendar. You can also paste a schedule or attach a document or photo to make several events at once.

Why is my calendar event an hour, or a day, out?

An .ics file can express a time in three ways, and the wrong one is nearly always the cause. A floating time (DTSTART:20260815T090000, no zone) is nine o'clock wherever it is opened. A UTC time (a trailing Z) is one absolute instant. A named zone (DTSTART;TZID=Europe/London:...) is an instant that stays at the same local clock time across daylight saving. An hour-out import is usually a Windows-style zone name such as 'GMT Standard Time' that the reading calendar does not recognise and falls back to UTC on; a day-out all-day event is usually a midnight timestamp where VALUE=DATE was needed, or an end date written on the last day rather than the day after, since DTEND is exclusive. ICS Maker writes a floating time by default and a TZID naming an IANA zone when one is chosen — without a bundled VTIMEZONE block, which every mainstream calendar resolves from the zone name itself.

The three ways a file can say when

Floating — no zone at all
DTSTART:20260815T090000. Nine in the morning wherever it is opened. Right for a local appointment, a reminder, or anything defined by the reader’s own clock; wrong the moment two people in different countries need to meet.
UTC — an absolute instant
DTSTART:20260815T090000Z, with the trailing Z. One moment in time, converted to local time by whatever opens it. Unambiguous, but it loses the fact that the meeting was “ten o’clock in London”, so a daylight-saving change moves it.
Named zone — an instant that survives daylight saving
DTSTART;TZID=Europe/London:20260815T090000. What a recurring meeting wants: the series stays at ten o’clock local even as the offset shifts underneath it. RFC 5545 asks for a matching VTIMEZONE block defining that zone’s offsets alongside it.

This builder writes the first by default and the third when you pick a zone from the list. That default is deliberate: a dentist appointment at nine should be at nine, and attaching the zone of whatever machine happened to build the file is how an event ends up an hour out for the person who reads it.

It writes the TZID without a bundled VTIMEZONE block, which is worth knowing before you send the file somewhere unusual. Apple Calendar, Google Calendar, Outlook, and Thunderbird all carry the IANA time-zone database and resolve Europe/London from the name alone, so the block would be several hundred lines restating what the reader already knows. A strict parser that resolves only the zones defined in the file itself is the case where that trade does not pay — paste a VTIMEZONE block in by hand if you are feeding one.

Reading a file that arrived wrong

Open it in a text editor and look at the DTSTART line, because the answer is always there. A trailing Z with an offset you did not expect means the sender converted to UTC from a zone you do not share. A TZID naming something like GMT Standard Time rather than Europe/London is Microsoft Exchange’s spelling, and calendars that only know the IANA names may fall back to UTC — which is the classic hour-out import. A TZID naming a zone that is neither an IANA name nor defined by a VTIMEZONE block in the same file is the case every reader guesses at differently, and guesses at UTC often enough that it is the second thing to check.

The all-day event that moves a day

An all-day event is a date, not a time: DTSTART;VALUE=DATE:20260815. Written as a midnight timestamp instead, it becomes a real instant, and any conversion westwards drags it into the previous day. The end date is the other half of the trap — it is exclusive, so a single day on the 15th ends on the 16th, and a file that ends it on the 15th shows nothing at all in some calendars.

Questions

Why is my calendar event one hour off?
Almost always a daylight-saving mismatch: the file names a fixed UTC offset, or a Windows-style zone name the reading calendar does not recognise, and the reader falls back to UTC. Check the DTSTART line — if it ends in Z the time is absolute UTC, and if it carries a TZID that zone has to be spelled as an IANA name like Europe/Paris, or else be defined by a VTIMEZONE block in the same file. Mainstream calendars resolve the IANA name from their own copy of the time-zone database and need no such block.
Should I set a time zone or leave it off?
Leave it off when the event is defined by local clock time — an appointment, a reminder, a class that starts at nine wherever you are. Set one when the event happens at a single instant that guests in other zones must convert to, such as a call, a webinar, or a broadcast.
What is a floating time?
A date-time written with no zone and no trailing Z, which RFC 5545 says is to be interpreted as local time wherever it is read. It is the right choice more often than people expect, and the wrong one whenever two readers in different zones have to agree on a moment.
Why does my all-day event show up on the wrong day?
Because it was written as a timestamp at midnight rather than as a date value. A true all-day event uses VALUE=DATE with no time at all, so there is nothing to convert. Remember also that the end date is exclusive: a one-day event on the 15th has DTEND on the 16th.