All-day events land on the wrong day in Google Calendar
Timed meetings look fine, but birthdays, public holidays and out-of-office days from your Outlook feed sit one day early โ or stretch across two days. This is a different bug from the time zone problem, with a different cause.
The fix: an all-day event is stored as a date, not a moment in time, and by
the iCalendar standard a date has no time zone. When a feed attaches a TZID to a
VALUE=DATE property anyway โ or exports the all-day event as a timed event running
00:00โ00:00 in some zone โ the subscriber converts it into its own zone and the day slides.
The correct repair is to remove the time zone from date values, not to shift the dates.
The feed proxy does this automatically; the number it removed shows up as
allDayTzidStripped in the diagnostic output.
Why a date with a time zone is a contradiction
RFC 5545 has two different things that look similar. A DATE-TIME is an instant, and it
may carry a TZID to say which wall clock it refers to. A DATE is just a calendar
day, and it may not โ "the 10th of August" is the 10th of August in Tokyo and in Los Angeles, even though
those are not the same 24 hours.
A correct all-day event looks like this, with DTEND pointing at the day after the
last day (the end is exclusive):
BEGIN:VEVENT
DTSTART;VALUE=DATE:20260810
DTEND;VALUE=DATE:20260811
SUMMARY:Anna out of office
END:VEVENT
Two broken variants show up in Outlook feeds. The first attaches a zone to the date:
DTSTART;VALUE=DATE;TZID=China Standard Time:20260810
The subscriber now has a date that claims to be in UTC+8. Reading it in a zone behind that one, the day starts before midnight local time, and the event is drawn on the 9th. The second variant is worse: the event is exported as a timed event at midnight,
DTSTART;TZID=China Standard Time:20260810T000000
DTEND;TZID=China Standard Time:20260811T000000
which is a genuine 24-hour block, correctly converted to 18:00 on the 9th in Berlin. Google is not wrong here โ the feed asked for exactly that. It just does not look like an all-day event any more.
What the repair does
- Strips
TZIDfrom anyVALUE=DATEproperty. That restores the standard meaning of the date and stops the subscriber converting it. This is safe and lossless: the parameter had no legitimate meaning there. - Leaves the dates themselves alone. Shifting a date to compensate would be guessing, and it breaks the moment the reader is in a different zone from the one you guessed for.
- Does not convert midnight-to-midnight timed events into all-day events. Those are ambiguous โ a genuine 00:00โ00:00 booking is indistinguishable from a mis-exported all-day event, and rewriting them would corrupt real ones. If your feed has this variant, the diagnostic shows the events as ordinary timed entries and the fix has to happen in Outlook.
Confirm which variant you have
Open your published .ics URL in a browser and find the event, or run the feed through
diagnostic mode. Then read the DTSTART line:
What DTSTART looks like | Diagnosis | Fix |
|---|---|---|
DTSTART;VALUE=DATE:20260810 |
Correct already | The off-by-one is coming from somewhere else โ check whether the event was created as all-day in Outlook at all. |
DTSTART;VALUE=DATE;TZID=โฆ:20260810 |
Zone on a date | The proxy strips it. allDayTzidStripped will be non-zero. |
DTSTART;TZID=โฆ:20260810T000000 |
Exported as a timed event | Not repairable in transit without guessing. Re-create the event in Outlook with the All day checkbox ticked. |
DTSTART:20260810T000000Z |
Midnight UTC, timed | Same as above. Everyone east or west of UTC sees it on a neighbouring day. |
One legitimate off-by-one is not a bug. If an event ends on the 11th and Google
shows it finishing on the 10th, that is the exclusive DTEND working as specified โ the
event occupies the 10th and ends at the start of the 11th. Outlook's own UI hides this by showing an
inclusive end date, which is why the two applications appear to disagree.
Questions
Why are my Outlook all-day events one day earlier in Google Calendar?
Because the feed attaches a time zone to a date. An all-day event is a VALUE=DATE
property, which has no time zone by definition; when Outlook adds a TZID anyway, Google
converts the date into the viewer's zone and it lands on the previous day for anyone west of the zone
in the feed. Removing the TZID from date values fixes it without moving anything.
Should I shift the dates by a day to compensate?
No. The shift depends on the gap between the zone in the feed and the zone of whoever is reading it, so a fixed adjustment is only right for one reader and wrong for everyone else โ and it breaks again when they travel. Remove the invalid time zone instead.
Why does a multi-day event end a day early in Google Calendar?
Because DTEND for an all-day event is exclusive: an event covering the 10th is written
as DTSTART:20260810, DTEND:20260811. Outlook's interface displays an inclusive
end date, so the same event appears to end on the 10th in Outlook and on the 10th in Google โ but a feed
produced with an inclusive DTEND will genuinely be a day short.
Is this the same problem as everything showing in GMT?
No. Times shifted by a few hours across every event is the Windows time zone naming problem. Whole days moved on all-day events only is this one. A feed can have both, and the same proxy repairs both in one pass.