# logistics.demurrage What a shipping line charges for keeping its container too long. The same arithmetic serves both charges, called with different dates: | charge | startDate | endDate | |---|---|---| | demurrage (container full, in the terminal) | discharge from the vessel | gate-out full | | detention (container outside the terminal) | gate-out full | returned empty | | combined "D&D" tariffs | discharge | returned empty | ## Counting days Days are calendar days and both ends count: a container discharged on 1 March and collected on 5 March has been there 5 days. Tariffs differ on whether the discharge day is day 1; if yours starts counting the next day, pass the next day as `startDate`. Free time in working days (some carriers exclude weekends and holidays) is not handled here. Days 1 to `freeDays` are free. Every later day is charged at the rate of the tier whose `fromDay`..`toDay` contains it, and the tiers use the same day numbers as the tariff prints ("days 5-7 USD 75, days 8-14 USD 150, day 15 onwards USD 300"). With extended free time the free days simply swallow the early tiers: 10 free days on that tariff charges days 11-14 at USD 150 and then USD 300. If your contract restarts the tiers after extended free time, renumber them before calling. `freeTimeEnds` is the last free day (`startDate + freeDays - 1`), reported even when the container went back earlier, because that is the date operations plan against. It is correct across month ends and 29 February. ## Errors A chargeable day that no tier covers is an error naming the day, not a free day: a gap in a tariff table is a data mistake, and charging nothing for it would hide it. Overlapping tiers, a tier running backwards, a negative rate, mixed currencies, no tiers at all, negative free days and an end before the start are errors too. ## Money Each line is `days x dailyRate` in integer minor units, exactly; there is no rounding anywhere. The rate is per container: multiply for several.