Functional Weave
Code in Rust

health.gestational-age@1.0.1

impl/python.py

1,392 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_add_days import add_days, days_between, parse_iso_date  ← from dates.add-days ^1.0.0 · built alongside by fune
from .health_gestational_age_types import GestationalAge

#: Naegele's rule: 280 days (40+0 weeks) from the LMP for a 28-day cycle.
_TERM_DAYS = 280
#: 44+0 weeks: beyond this the dates are almost certainly wrong.
_MAX_DAYS = 308


def gestational_age(lmp_date: str, on_date: str, cycle_length_days: int) -> GestationalAge:
    """Gestational age and estimated due date from the last menstrual period.

    A cycle longer or shorter than 28 days moves ovulation, so both are shifted
    by the difference, as the NHS due date calculator does.
    """
    c = cycle_length_days
    if isinstance(c, bool) or not isinstance(c, int) or c < 20 or c > 44:
        raise ValueError("cycleLengthDays must be a whole number from 20 to 44, received %r" % (c,))
    parse_iso_date(lmp_date)
    parse_iso_date(on_date)
    shift = c - 28
    total_days = days_between(lmp_date, on_date) - shift
    if total_days < 0:
        raise ValueError("onDate %s is before the adjusted start of pregnancy" % (on_date,))
    if total_days > _MAX_DAYS:
        raise ValueError("gestational age of %d days is more than 44+0 weeks: check the dates" % (total_days,))
    return GestationalAge(
        weeks=total_days // 7,
        days=total_days % 7,
        total_days=total_days,
        due_date=add_days(lmp_date, _TERM_DAYS + shift),
    )