DateTimeImmutable prevents the modify() bug you will otherwise write

DateTime::modify() mutates the object and returns it. Because it returns something, it reads like a pure function, so it gets assigned to a new variable — and then both variables point at the same mutated object.

$start = new DateTime('2015-06-01');
$end   = $start->modify('+30 days');

echo $start->format('Y-m-d');  // 2015-07-01 — also moved

$start = new DateTimeImmutable('2015-06-01');
$end   = $start->modify('+30 days');

echo $start->format('Y-m-d');  // 2015-06-01

DateTimeImmutable has the same API and returns a new instance from every modifier, so the bug cannot be written. Both implement DateTimeInterface, which means a type hint on the interface accepts either — useful while migrating, and a good default for anything a date is passed into.