Cumulative Duty Caps Compared

The exact question this guide answers is which cumulative cap catches a heavy roster first, and why a block that clears every FAA window can still breach an EASA one. The two regimes both limit accumulated duty, but they count over different intervals — the FAA over rolling hours (168 and 672), EASA over rolling days (7, 14, and 28) — and they meter different quantities, FDP hours under the FAA and duty hours under EASA. The result is a genuine gap: the EASA 14-day cap has no FAA analogue, so a fortnight of dense flying can be legal in the United States and illegal in Europe. This page runs one two-week block through both sets of windows, reports which binds, and shows the rolling-window code behind the FAA vs EASA scenario comparisons. The caps themselves come from the regulatory reference tables, and the rolling aggregation mirrors the duty time validation rule engines.

Prerequisites

The scenario, stated precisely

A crew member flies a dense 14-day block that accumulates 112 duty hours and 104 FDP hours, spread so that no single rolling 168-hour window exceeds 58 FDP hours. The question is whether the block is legal, and under which regime.

Step 1 — Evaluate the FAA rolling-hour windows

The FAA caps FDP hours at 60 in any 168 consecutive hours and 190 in any 672 consecutive hours. With a peak of 58 FDP hours in the worst 168-hour window and 104 over the whole fortnight, the block clears both FAA windows — the 672-hour (28-day) cap of 190 is nowhere near binding at two weeks.

CAPS = {
    "FAA": [
        {"metric": "fdp", "window_hours": 168, "cap_minutes": 60 * 60},
        {"metric": "fdp", "window_hours": 672, "cap_minutes": 190 * 60},
    ],
    "EASA": [
        {"metric": "duty", "window_hours": 7 * 24, "cap_minutes": 60 * 60},
        {"metric": "duty", "window_hours": 14 * 24, "cap_minutes": 110 * 60},
        {"metric": "duty", "window_hours": 28 * 24, "cap_minutes": 190 * 60},
    ],
}


def worst_window(duties, metric, window_hours):
    """Max sum of `metric` minutes over any trailing window of the given length."""
    from datetime import timedelta
    span = timedelta(hours=window_hours)
    worst = 0
    for i, anchor in enumerate(duties):
        total = sum(
            d[metric] for d in duties
            if anchor["report"] - span < d["report"] <= anchor["report"]
        )
        worst = max(worst, total)
    return worst

Verify: for this block, worst_window(duties, "fdp", 168) returns 3480 minutes (58 hours), below the 3600-minute (60-hour) FAA cap, and the 672-hour window is far below 190 hours. The FAA verdict is compliant.

Step 2 — Evaluate the EASA rolling-day windows

EASA caps duty hours at 60 in any 7 days, 110 in any 14 days, and 190 in any 28 days. The 14-day window is the one with no FAA counterpart, and the block’s 112 duty hours over the fortnight exceed the 110-hour cap by two hours. EASA fails the block.

def evaluate(duties, regime):
    results = []
    for cap in CAPS[regime]:
        worst = worst_window(duties, cap["metric"], cap["window_hours"])
        results.append({
            "regime": regime,
            "window_hours": cap["window_hours"],
            "metric": cap["metric"],
            "worst_minutes": worst,
            "cap_minutes": cap["cap_minutes"],
            "breached": worst > cap["cap_minutes"],
        })
    return results


easa = evaluate(duties, "EASA")
breached = [r for r in easa if r["breached"]]
# breached -> the 14-day duty window: 6720 worst vs 6600 cap

Verify: evaluate(duties, "EASA") flags the 336-hour (14-day) window as breached — 6720 worst-window minutes against the 6600-minute (110-hour) cap — while the 7-day and 28-day windows stay clear.

Step 3 — Reconcile and report the binding regime

The block is legal under the FAA and illegal under EASA, so for a dual-jurisdiction crew EASA binds and the roster must be rebuilt to shed at least two duty hours from the worst 14-day window.

def reconcile_caps(faa, easa):
    faa_ok = not any(r["breached"] for r in faa)
    easa_ok = not any(r["breached"] for r in easa)
    binding = None if faa_ok and easa_ok else ("EASA" if not easa_ok else "FAA")
    return {"faa_compliant": faa_ok, "easa_compliant": easa_ok, "binding_regime": binding}


verdict = reconcile_caps(evaluate(duties, "FAA"), easa)
# {'faa_compliant': True, 'easa_compliant': False, 'binding_regime': 'EASA'}
FAA hour-windows vs EASA day-windows over a fortnight Over a 14-day block, the FAA meters FDP hours in a 168-hour and a 672-hour rolling window, both compliant. EASA meters duty hours in 7-day, 14-day, and 28-day windows; the 14-day window, which has no FAA counterpart, is breached at 112 duty hours against a 110-hour cap. The 14-day window is highlighted as the binding constraint. FAA — FDP hours EASA — duty hours 168 h 58 / 60 h · ok 672 h 104 / 190 h · ok 7 d 59 / 60 h · ok 14 d 112 / 110 h · BREACH · binds 28 d 112 / 190 h · ok No FAA window spans 14 days — the EASA-only gap.
The FAA jumps from a 168-hour window to a 672-hour window with nothing in between; the EASA 14-day cap sits squarely in that gap, so a 112-hour fortnight passes the FAA and fails EASA.

Verification queries and assertions

faa = evaluate(duties, "FAA")
easa = evaluate(duties, "EASA")
assert all(not r["breached"] for r in faa)                      # FAA clears every window
assert any(r["window_hours"] == 336 and r["breached"] for r in easa)  # EASA 14-day fails
assert reconcile_caps(faa, easa)["binding_regime"] == "EASA"

The middle assertion is the whole point: the breach lives in the 336-hour (14-day) window, the interval the FAA does not meter, so only the EASA evaluation catches it.

Failure modes and troubleshooting

Frequently Asked Questions

Why does the FAA miss a breach the EASA rules catch?

Because the FAA has no cumulative window between 168 hours (about a week) and 672 hours (about four weeks). A two-week accumulation falls in that gap, where the EASA 14-day cap of 110 hours sits with no American counterpart.

Are the 7-day EASA cap and the 168-hour FAA cap the same rule?

No. The windows are nearly the same length, but the FAA cap counts 60 flight-duty-period hours while the EASA cap counts 60 duty hours. Duty is the broader quantity, so the EASA 7-day cap can bind on a roster the FAA 168-hour cap clears.

How much duty must come out of the roster to pass EASA?

At least two hours from the worst 14-day window, since the block sits at 112 duty hours against the 110-hour cap. The rebuild must target that specific window, not the fortnight total, because the cap is on any rolling 14 days.

Does augmentation change these cumulative caps?

Augmentation raises the daily FDP ceiling, not the cumulative caps evaluated here. The 60/190 FAA hours and the 60/110/190 EASA hours apply regardless of crew complement, so an augmented long-haul block still meters against the same windows.

Back to FAA vs EASA Scenario Comparisons.