from datetime import date, timedelta
def workdays_between(a, b):
"""Count working days from date a to date b (negative if b is earlier)."""
step = 1 if b >= a else -1
d, n = a, 0
while d != b:
d += timedelta(days=step)
if d.weekday() < 5:
n += step
return n
milestones = [("Scope signed", date(2026, 11, 5), date(2026, 11, 5)),
("Design approved", date(2026, 11, 10), date(2026, 11, 10)),
("Code complete", date(2026, 11, 18), date(2026, 11, 25)),
("Accepted", date(2026, 11, 25), date(2026, 12, 3)),
("Review report", date(2026, 11, 26), date(2026, 12, 10))]
for name, planned, actual in milestones:
slip = workdays_between(planned, actual)
print(f"{name:<16}{planned:%b %d} -> {actual:%b %d} slip {slip:+d} days")
planned_hours, actual_hours = 110, 141
change = (actual_hours - planned_hours) / planned_hours
print(f"Effort: {planned_hours} h planned, {actual_hours} h actual ({change:+.0%})")