impl/typescript.ts
1,422 bytes · the TypeScript 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.
import { addDays, daysBetween, parseIsoDate } from "./dates_add_days.ts"; ← from dates.add-days ^1.0.0 · built alongside by fune
import { type GestationalAge } from "./health_gestational_age_types.ts";
/** Naegele's rule: 280 days (40+0 weeks) from the LMP for a 28-day cycle. */
const TERM_DAYS = 280;
/** 44+0 weeks: beyond this the dates are almost certainly wrong. */
const MAX_DAYS = 308;
/**
* 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.
*/
export function gestationalAge(lmpDate: string, onDate: string, cycleLengthDays: number): GestationalAge {
if (!Number.isInteger(cycleLengthDays) || cycleLengthDays < 20 || cycleLengthDays > 44) {
throw new RangeError(`cycleLengthDays must be a whole number from 20 to 44, received ${cycleLengthDays}`);
}
parseIsoDate(lmpDate);
parseIsoDate(onDate);
const shift = cycleLengthDays - 28;
const totalDays = daysBetween(lmpDate, onDate) - shift;
if (totalDays < 0) {
throw new RangeError(`onDate ${onDate} is before the adjusted start of pregnancy`);
}
if (totalDays > MAX_DAYS) {
throw new RangeError(`gestational age of ${totalDays} days is more than 44+0 weeks: check the dates`);
}
return {
weeks: Math.floor(totalDays / 7),
days: totalDays % 7,
totalDays,
dueDate: addDays(lmpDate, TERM_DAYS + shift),
};
}