from typing import Sequence from .charts_scale_linear_scale import interpolate, pair from .dates_days_between import days_between from .math_round_float import round_float def time_scale(domain: Sequence[str], range: Sequence[float], value: str, clamp: bool) -> float: """Where an ISO date lands on the range, linearly by calendar days. Days are counted with dates.days-between, never through datetime, so no time zone can move a point by a day. """ if len(domain) != 2: raise ValueError(f"domain must have exactly 2 values, [from, to]; got {len(domain)}") r0, r1 = pair(range, "range") span = days_between(domain[0], domain[1]) if span == 0: raise ValueError(f"domain has no width: both ends are {domain[0]}") t = days_between(domain[0], value) / span if clamp: t = max(0.0, min(1.0, t)) return round_float(interpolate(r0, r1, t), 6)