Why Your ICS All-Day Event Shows an Extra Day
Read ICS all-day start and end dates, distinguish date-only events from midnight timestamps, and correct extra-day errors without shifting valid events.
On this page
An ICS all-day event ends before its DTEND date. A one-day event on November 10 should therefore start on 20261110 and end on 20261111. Seeing the next day's date in the file is correct; seeing the event occupy that next date needs investigation.
This exclusive end boundary is part of the event definition in RFC 5545 §3.6.1. Do not subtract one day from every end date.
Key Takeaways
DTENDis the first date outside a date-only all-day event.VALUE=DATErepresents calendar dates; midnight timestamps represent timed events.- Establish the intended occupied dates before editing either boundary.
- Compare the source, parsed values, and target calendar display separately.
Write down the dates the event should occupy
Start with the human schedule. For example: “The office is closed on November 10 only,” or “The workshop runs all day on November 10 and 11.”
Then compare that intent with the fields:
| Intended occupied dates | DTSTART;VALUE=DATE | DTEND;VALUE=DATE |
| --- | --- | --- |
| November 10 only | 20261110 | 20261111 |
| November 10 and 11 | 20261110 | 20261112 |
| December 31 and January 1 | 20261231 | 20270102 |
These are boundary calculations, not observations of a particular app. If the source matches this table but the display differs, collect evidence from the receiving application before changing a valid file.
Read a complete one-day example
This synthetic file defines a one-day office closure. Save it as UTF-8 with CRLF line endings.
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//CalendarLint//All-Day Example//EN
BEGIN:VEVENT
UID:office-closure@example.test
DTSTAMP:20261105T000000Z
DTSTART;VALUE=DATE:20261110
DTEND;VALUE=DATE:20261111
SUMMARY:Office closed
END:VEVENT
END:VCALENDAR
The expected occupied date is November 10, 2026 only. November 11 is the boundary where the event has finished.
For a two-day closure on November 10 and 11, change only the end to 20261112. That makes a useful controlled pair: the title, identity, and start date stay the same, while the occupied span changes by one date.
If the actual intention was two days, the second version is correct. An “extra day” can be a mismatch with the intended schedule rather than a syntax error.
Distinguish all-day dates from midnight times
A midnight-to-midnight event can look like an all-day event in one view, but its fields describe something different.
DTSTART:20261110T000000Z
DTEND:20261111T000000Z
These are UTC timestamps. In a display zone at UTC−08:00, the interval runs from November 9 at 16:00 to November 10 at 16:00. It touches two local dates even though it lasts exactly 24 hours.
Compare that with:
DTSTART;VALUE=DATE:20261110
DTEND;VALUE=DATE:20261111
The second pair describes date boundaries without a time of day. TZID is not applied to a DATE value. The standard distinguishes these value types in its DATE and DATE-TIME definitions.
Replacing a timed interval with dates changes its meaning. Make that change only when the source owner confirms it was intended as an all-day event.
Choose the fix from the evidence
Inspect the event's exact fields in a text editor or CalendarLint's Source view. Then use this decision table:
| What you find | Likely issue to investigate | Defensible next step |
| --- | --- | --- |
| Correct date-only boundaries, wrong display | Receiving app interpretation or display | Test an unchanged control in a temporary calendar |
| End date is one day later than the confirmed intended boundary | Source generator's boundary calculation | Correct that event or generator after confirming intent |
| UTC midnight timestamps | Timed data being treated as an all-day schedule | Ask whether the event should represent dates or instants |
| A date-only start and timestamp end | Inconsistent value types | Restore the intended matching types from authoritative data |
| No DTEND on a date-only event | Possibly intentional one-day representation | Do not add an end solely because it is absent |
RFC 5545 defines a date-only event with neither DTEND nor DURATION as having a one-day duration. A missing end is therefore not automatically a defect.
Do not add 23:59:59 to imitate an all-day endpoint. That creates a timed representation and introduces a different boundary.
Verify the repaired copy
Keep the original and change one known field at a time. In CalendarLint, compare Calendar and Source, then follow the repair and safe-export workflow if a correction is warranted.
For each case, record the intended dates, raw start and end values, target app and version, display time zone, and visible occupied dates. Test the one-day, two-day, and midnight examples separately. This makes it possible to identify whether the mismatch began in the exporter, the file, or the receiving display.
Verification scope: the one-day and two-day synthetic variants were parsed with ical.js 2.2.1 on November 5, 2026; their date types and boundary spans were checked. The UTC−08:00 example is an explicit offset calculation. No Google, Apple, or Outlook display results are claimed.

