← Blog

Overnight flights and the day that changes

A red-eye departs one day and lands the next. SSIM encodes that with a day offset — and the 2400-vs-0000 midnight edge — which naive time handling turns into negative block times and arrivals before departure.

An overnight flight leg spanning two calendar days with a +1 arrival-day offset highlighted, in Active Flights brand cyan on near-black.

A flight departs at 23:40 and arrives at 06:15. Six hours thirty-five in the air? Or a negative six-hour flight that lands before it left? Both answers come out of the same SSIM record depending on one detail a lot of code gets wrong: the day changed in between. This is the humble overnight leg, and it breaks more schedule parsers than almost anything else.

Two times, and the day that’s missing between them

A flight-leg record gives you a departure time and an arrival time — and that’s it on the same line. Both are wall-clock times, four digits, HHMM. There is no date attached to the arrival. The record’s period and days of operation tell you which days the flight departs; the arrival day is implied.

For a daytime hop that implication is harmless — depart 09:00, arrive 10:30, same day. For a red-eye it is the whole problem. Depart 23:40, arrive 06:15, and a reader that assumes same-day arrival computes an arrival time earlier than the departure.

Depart  2340
Arrive  0615      ← next day, but the record doesn't repeat the date
Naive:  0615 − 2340  =  −1285 minutes   ("lands before it left")

The day offset

SSIM handles this with a day-change indicator on the arrival side of the leg — a small signed offset that says how many calendar days after the departure the arrival falls. For the overnight above, the arrival day offset is +1: same clock time, next day.

Most overnights are +1. But the field is not decorative:

  • A flight can cross enough time zones that it arrives on the same local day it left, or even the day before in local terms — a westbound long-haul chasing the sun. The offset can legitimately be 0 or negative.
  • A very long leg through multiple date boundaries can land two days later.

The rule is simple once you respect the field: the arrival’s real moment is arrival time on departure date + day offset. Ignore the offset and you have thrown away the one piece of information that makes the arrival unambiguous.

midnight — 2400 of day D = 0000 of day D+1 day D day D+1 depart 2330 arrive 0640 arrival day offset +1 block 7h 10m →
The arrival clock (0640) is earlier than the departure clock (2330) — only the +1 day offset makes the leg positive instead of negative.

A red-eye isn’t an anomaly in the data. It’s a perfectly normal flight that only looks impossible when you drop the day.

The 2400-versus-0000 edge

Then there’s midnight, which the format lets you write two ways.

Midnight at the end of a day can appear as 2400 — hour twenty-four of the day that’s ending — or as 0000, hour zero of the day that’s beginning. They name the same instant from opposite sides of the boundary. A flight arriving exactly at midnight might carry 2400 with no day offset, or 0000 with a +1 offset. Both are correct. Both must resolve to the same moment.

The trap is arithmetic. Treat 2400 as an ordinary time and a lot of libraries either reject it (only 00002359 are “valid”) or silently wrap it to 0000 of the same day — which is now midnight at the start of the day, twenty-four hours early. A scheduled arrival of 2400 that gets read as 0000 without advancing the date turns a full overnight into a zero-length or negative block.

Written Means If read naively as start-of-day
0000 Midnight, start of day Correct
2400 Midnight, end of day 24 hours early → zero/negative block

The safe reading is to normalise 2400 to 0000 of the next day — advance the date by one as you collapse the hour — so the instant is preserved. Handle it anywhere else and the bug hides until a report shows a flight with a block time of zero.

Why it stays silent

The reason the day change causes so much quiet damage is that nothing crashes. A negative duration is a perfectly representable number; a zero-length block sails through most schemas. The flight is still in the file, still counted, still shown — it’s just wrong in a way you only notice when someone sums block hours, sorts by arrival, or tries to build a connection off the back of it and the numbers don’t reconcile.

It compounds with the time-zone problem, too. Local times, per-station UTC offsets, and the day change are three separate corrections that all have to be applied together. Get the day right but the offset wrong, or the offset right but the midnight edge wrong, and you still land in the same place: a duration that doesn’t match reality. These are exactly the kind of edge cases that look like errors, aren’t, and punish the naive reading.

Doing it right

The discipline is small and non-negotiable:

  • Read the day offset. The arrival’s date is departure date plus the offset — never assume same-day.
  • Normalise 2400 to 0000 of the next day before you do any arithmetic, so midnight is one instant, not two contradictory ones.
  • Compute durations across the boundary, adding a day’s worth of minutes when the arrival clock is earlier than the departure clock, so an overnight reads as a positive block rather than a negative one.

None of that is exotic. It’s just easy to skip, and expensive to skip quietly.

This is the kind of thing SSIM Toolkit handles for you: it surfaces the arrival’s +1 (or 0, or +2) day offset explicitly, treats the 2400/0000 midnight edge as one instant, and computes block time across the day change so an overnight comes back as a sensible positive duration instead of a red flag. You can see the day the flight lands without doing the calendar arithmetic in your head. More on SSIM Toolkit.

Next in the series, we take the other half of this problem head-on: computing block time UTC-correct.


Early Access Preview

Want early access?

We're opening SSIM Toolkit to teams in waves through 2026 — free during the preview. Drop your email and we'll reach out when it's your turn.