Functional Weave
Code in TypeScript

energy.estimate-read@1.0.0

impl/python.py

1,404 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from .dates_days_between import days_between  ← from dates.days-between ^1.0.0 · built alongside by fune
from .energy_estimate_read_types import EstimatedRead, MeterRead
from .energy_meter_advance import meter_advance  ← from energy.meter-advance ^1.0.0 · built alongside by fune
from .math_round_div import RoundingMode, round_div  ← from math.round-div ^1.0.0 · built alongside by fune

MAX_SAFE = 9007199254740991


def estimate_read(
    earlier_read: MeterRead, latest_read: MeterRead, on_date: str, digits: int, mode: RoundingMode
) -> EstimatedRead:
    """Carry the latest read forward to ``on_date`` at the average daily
    consumption between the two reads, rounding once, and wrap past all nines.
    """
    consumption = meter_advance(earlier_read.value, latest_read.value, digits)
    history = days_between(earlier_read.date, latest_read.date)
    if history <= 0:
        raise ValueError(
            "the earlier read must be dated before the latest read, received %s and %s"
            % (earlier_read.date, latest_read.date)
        )
    ahead = days_between(latest_read.date, on_date)
    if ahead < 0:
        raise ValueError(
            "onDate must not be before the latest read, received %s and %s" % (on_date, latest_read.date)
        )
    product = consumption * ahead
    if product > MAX_SAFE:
        raise ValueError("estimate too large to calculate exactly")
    units = round_div(product, history, mode)
    span = 10**digits
    raw = latest_read.value + units
    return EstimatedRead(read=raw % span, units=units, rolled_over=raw >= span)