from .dates_add_days import epoch_day_from_iso def overlap_days(a_start: str, a_end: str, b_start: str, b_end: str, end_inclusive: bool) -> int: """Days two ranges have in common. ``end_inclusive`` says whether each end date is the range's last day (a statement period) or the day after it (a half-open range, a hotel stay); both ranges use the same convention. """ a0 = epoch_day_from_iso(a_start) a1 = epoch_day_from_iso(a_end) b0 = epoch_day_from_iso(b_start) b1 = epoch_day_from_iso(b_end) if a1 < a0: raise ValueError("range A starts %s, after its end %s" % (a_start, a_end)) if b1 < b0: raise ValueError("range B starts %s, after its end %s" % (b_start, b_end)) # An inclusive end is the half-open end one day later. extra = 1 if end_inclusive else 0 days = min(a1, b1) + extra - max(a0, b0) return days if days > 0 else 0