{
  "schemaVersion": 1,
  "slug": "week-number-calculator",
  "category": "date-time",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "db74a2def62b59ee77b25f2fc21f45fe866a65c83bc710a43aea67afddc26d96",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/week-number-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": "W = 1 + round((T_d − T_1) ÷ 7)",
    "vars": [
      [
        "T_d",
        "Thursday of the date's week"
      ],
      [
        "T_1",
        "Thursday of week 1 (contains Jan 4)"
      ],
      [
        "W",
        "ISO 8601 week number"
      ]
    ],
    "note": "Date is shifted to its Thursday (Monday starts the week); ISO year is that Thursday's year. 53 weeks when Jan 1 is Thursday, or Wednesday in a leap year; day-of-year and quarter also output."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const d=new Date(date+'T00:00:00Z'); if(!Number.isFinite(d.getTime()))return{isoWeek:null,isoYear:null,dayOfYear:null,weeksInYear:null,quarter:null,__error:'inputError'}; const target=new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate())); const dayNum = (target.getUTCDay()+6)%7; target.setUTCDate(target.getUTCDate()-dayNum+3); const firstThursday = new Date(Date.UTC(target.getUTCFullYear(),0,4)); const fdayNum = (firstThursday.getUTCDay()+6)%7; firstThursday.setUTCDate(firstThursday.getUTCDate()-fdayNum+3); const isoWeek = 1 + Math.round((target-firstThursday)/(7*86400000)); const jan1 = new Date(Date.UTC(d.getUTCFullYear(),0,1)); const jan1Day = jan1.getUTCDay(); const leap = (d.getUTCFullYear()%4===0 && d.getUTCFullYear()%100!==0) || d.getUTCFullYear()%400===0; const weeks = (jan1Day===4 || (leap && jan1Day===3)) ? 53 : 52; return { isoWeek, isoYear: target.getUTCFullYear(), dayOfYear: Math.round((d-jan1)/86400000)+1, weeksInYear: weeks, quarter: Math.floor(d.getUTCMonth()/3)+1 };",
    "inputs": [
      {
        "name": "date",
        "type": "date",
        "default": "@today",
        "step": 1
      }
    ],
    "outputs": [
      {
        "name": "isoWeek",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "isoYear",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "dayOfYear",
        "precision": 0,
        "unit": "days"
      },
      {
        "name": "weeksInYear",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "quarter",
        "precision": 0,
        "unit": ""
      }
    ],
    "interpret": null
  }
}
