{
  "schemaVersion": 1,
  "slug": "conception-date-calculator",
  "category": "date-time",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "0506f1b44b1ccb55f225749b2abbb6e48b39ea70793a17e46797c52091e46935",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/conception-date-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "LMP = D − (280 + c − 28); C_d = D − 266",
    "vars": [
      [
        "D",
        "due date"
      ],
      [
        "c",
        "cycle length in days"
      ],
      [
        "LMP",
        "last menstrual period"
      ],
      [
        "C_d",
        "conception date"
      ]
    ],
    "note": "LMP = D − (280 + c − 28); conception = D − 266. The entered cycle length shifts the estimated LMP, while conception remains 266 days before the fixed due date under this model."
  },
  "externalEvidence": {
    "reviewedAt": "2026-10-12",
    "sources": [
      {
        "name": "ACOG — Methods for estimating the due date",
        "url": "https://www.acog.org/clinical/clinical-guidance/committee-opinion/articles/2017/05/methods-for-estimating-the-due-date"
      }
    ],
    "referenceRole": "context",
    "implementationHash": "0506f1b44b1ccb55f225749b2abbb6e48b39ea70793a17e46797c52091e46935",
    "basis": "LMP = D − (280 + c − 28); C_d = D − 266",
    "limitations": "The references provide context and limitations. They do not validate this page’s illustrative multipliers, lookup values or predictions."
  },
  "contract": {
    "compute": "const empty={conceptionDate:null,lastPeriod:null,gestationalDays:null};const parse=s=>{const m=/^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(String(s));if(!m)return null;const y=+m[1],mo=+m[2]-1,day=+m[3],d=new Date(0);d.setUTCHours(0,0,0,0);d.setUTCFullYear(y,mo,day);return d.getUTCFullYear()===y&&d.getUTCMonth()===mo&&d.getUTCDate()===day?d:null;};const due=parse(dueDate),cycle=Number(cycleLength),DAY=86400000;if(!due||due.getUTCFullYear()<1900||due.getUTCFullYear()>2100||!Number.isInteger(cycle)||cycle<20||cycle>45)return{...empty,__error:'inputError'};const lmp=new Date(due.getTime()-(280+cycle-28)*DAY),conception=new Date(due.getTime()-266*DAY),now=new Date(),today=new Date(Date.UTC(now.getFullYear(),now.getMonth(),now.getDate()));return{conceptionDate:conception.toISOString().slice(0,10),lastPeriod:lmp.toISOString().slice(0,10),gestationalDays:Math.max(Math.round((today-lmp)/DAY),0)};",
    "inputs": [
      {
        "name": "dueDate",
        "type": "date",
        "default": "@today+8m",
        "step": 1
      },
      {
        "name": "cycleLength",
        "type": "number",
        "default": 28,
        "min": 20,
        "max": 45,
        "step": 1,
        "slider": true
      }
    ],
    "outputs": [
      {
        "name": "conceptionDate",
        "precision": 0,
        "unit": "",
        "type": "text"
      },
      {
        "name": "lastPeriod",
        "precision": 0,
        "unit": "",
        "type": "text"
      },
      {
        "name": "gestationalDays",
        "precision": 0,
        "unit": "days"
      }
    ],
    "interpret": null
  }
}
