{
  "ad": "Hangi Gün, Hafta Numarası ve Yılın Kaçıncı Günü",
  "surum": "1.0.0",
  "aciklama": "Bir Gregoryen tarihin gün adını, ISO-8601 hafta numarası ile ISO yılını, ordinal gününü ve takvim ayrıntılarını; ikinci tarih verilirse işaretli tarih farklarını UTC tabanlı deterministik kurallarla hesaplar.",
  "calismaModeli": {
    "tur": "tarayici-ici-saf-fonksiyon",
    "fonksiyon": "hesapla(girdi)",
    "cekirdekIsaretleri": [
      "/*__CALC_BASLA__*/",
      "/*__CALC_BITIS__*/"
    ],
    "agGereksinimi": false,
    "zamanDilimiBagimsiz": true
  },
  "girdiler": [
    {
      "ad": "tarih",
      "tip": "string",
      "bicim": "YYYY-MM-DD",
      "zorunlu": true,
      "kisit": "1583-01-01 ile 9999-12-31 arasında geçerli Gregoryen tarih",
      "aciklama": "Ana tarih. Geçersiz günler sonraki aya taşınmaz."
    },
    {
      "ad": "ikinciTarih",
      "tip": [
        "string",
        "null"
      ],
      "bicim": "YYYY-MM-DD",
      "zorunlu": false,
      "kisit": "Verilirse tarih ile aynı sınırlar",
      "aciklama": "Gün, hafta, tam takvim ayı ve iş günü farkını etkinleştirir."
    },
    {
      "ad": "haftaBaslangici",
      "tip": "string",
      "zorunlu": false,
      "varsayilan": "pazartesi",
      "enum": [
        "pazartesi",
        "pazar"
      ],
      "aciklama": "Kanonik ISO sonucunu değiştirmez. pazar seçimi, POSIX %U konvansiyonundaki ikincil gösterimi vurgular."
    },
    {
      "ad": "tatilGunleri",
      "tip": "array",
      "ogeTipi": "YYYY-MM-DD string",
      "zorunlu": false,
      "varsayilan": [],
      "aciklama": "İş günü hesabından düşülecek kullanıcı tanımlı tarihler. Yinelenenler bir kez, hafta sonuna gelenler sıfır ek etkiyle uygulanır."
    }
  ],
  "cikti": {
    "tip": "object",
    "required": [
      "tarih",
      "gunAdi",
      "isoGunNo",
      "isoHafta",
      "haftaPazarBaslangicli",
      "yilinGunu",
      "kalanGun",
      "yildakiGunSayisi",
      "yilinYuzdesi",
      "ceyrek",
      "ayinKacinciHaftasi",
      "artikYil",
      "yildakiISOHaftaSayisi",
      "fark",
      "uyarilar",
      "hata"
    ],
    "properties": {
      "tarih": {
        "tip": [
          "string",
          "null"
        ],
        "aciklama": "Ana girdi tarih metni. Başarılı sonuçta doğrulanmıştır; hata sonucunda çekirdeğin aldığı doğrulanmamış string metin aynen korunabilir, string değilse null olur."
      },
      "gunAdi": {
        "tip": [
          "string",
          "null"
        ],
        "enumBasarili": [
          "Pazartesi",
          "Salı",
          "Çarşamba",
          "Perşembe",
          "Cuma",
          "Cumartesi",
          "Pazar"
        ]
      },
      "isoGunNo": {
        "tip": [
          "integer",
          "null"
        ],
        "birim": "gun-sira-numarasi",
        "minimum": 1,
        "maximum": 7,
        "aciklama": "Pazartesi=1, Pazar=7."
      },
      "isoHafta": {
        "tip": [
          "object",
          "null"
        ],
        "required": [
          "isoYil",
          "hafta",
          "etiket"
        ],
        "properties": {
          "isoYil": {
            "tip": "integer",
            "birim": "yil",
            "aciklama": "Haftanın Perşembe gününün yılı; takvim yılından farklı olabilir."
          },
          "hafta": {
            "tip": "integer",
            "birim": "iso-hafta-numarasi",
            "minimum": 1,
            "maximum": 53
          },
          "etiket": {
            "tip": "string",
            "desen": "^[0-9]{4}-W[0-9]{2}$"
          }
        }
      },
      "haftaPazarBaslangicli": {
        "tip": [
          "integer",
          "null"
        ],
        "birim": "posix-hafta-numarasi",
        "minimum": 0,
        "maximum": 53,
        "aciklama": "POSIX %U: ilk Pazar hafta 1, öncesi hafta 0. ISO değildir."
      },
      "yilinGunu": {
        "tip": [
          "integer",
          "null"
        ],
        "birim": "gun",
        "minimum": 1,
        "maximum": 366
      },
      "kalanGun": {
        "tip": [
          "integer",
          "null"
        ],
        "birim": "gun",
        "minimum": 0,
        "maximum": 365,
        "aciklama": "Seçilen gün hariç yıl sonuna kalan gün."
      },
      "yildakiGunSayisi": {
        "tip": [
          "integer",
          "null"
        ],
        "birim": "gun",
        "enumBasarili": [
          365,
          366
        ]
      },
      "yilinYuzdesi": {
        "tip": [
          "number",
          "null"
        ],
        "birim": "yuzde",
        "minimum": 0,
        "maximum": 100,
        "ondalik": 2
      },
      "ceyrek": {
        "tip": [
          "integer",
          "null"
        ],
        "birim": "ceyrek-sira-numarasi",
        "minimum": 1,
        "maximum": 4
      },
      "ayinKacinciHaftasi": {
        "tip": [
          "integer",
          "null"
        ],
        "birim": "ay-ici-takvim-haftasi-sira-numarasi",
        "minimum": 1,
        "maximum": 6,
        "aciklama": "Ürün kararı: Pazartesi–Pazar takvim satırı; ayın 1'ini içeren kısmi satır hafta 1."
      },
      "artikYil": {
        "tip": [
          "boolean",
          "null"
        ]
      },
      "yildakiISOHaftaSayisi": {
        "tip": [
          "integer",
          "null"
        ],
        "birim": "iso-hafta-adedi",
        "enumBasarili": [
          52,
          53
        ],
        "aciklama": "Ana tarihin yıl numarasıyla etiketlenen ISO hafta yılının 52/53 uzunluğu; tarihin isoHafta.isoYil alanına göre değil."
      },
      "fark": {
        "tip": [
          "object",
          "null"
        ],
        "required": [
          "ikinciTarih",
          "gunFarki",
          "haftaFarki",
          "tamAyFarki",
          "isGunu",
          "resmiTatilDahilDegil"
        ],
        "properties": {
          "ikinciTarih": {
            "tip": "string",
            "bicim": "YYYY-MM-DD"
          },
          "gunFarki": {
            "tip": "integer",
            "birim": "gun",
            "aciklama": "(ikinciTarih UTC - tarih UTC) / 86400000"
          },
          "haftaFarki": {
            "tip": "number",
            "birim": "hafta",
            "ondalik": 1,
            "aciklama": "gunFarki / 7 değerinin bir ondalığa yuvarlanmış sayısal hali."
          },
          "tamAyFarki": {
            "tip": "integer",
            "birim": "tam-takvim-ayi",
            "aciklama": "Takvim ayları ve gün bileşeniyle düzeltilmiş, işaretli tamamlanmış ay sayısı."
          },
          "isGunu": {
            "tip": "integer",
            "birim": "is-gunu",
            "aciklama": "Kronolojik (erken, geç] aralığındaki Pzt–Cum sayısının giriş yönüyle işaretlenmiş hali; kullanıcı tatilleri düşülür."
          },
          "resmiTatilDahilDegil": {
            "tip": "boolean",
            "aciklama": "true ise tatil listesi boş olduğu için yalnız hafta sonları düşülmüştür. false, kullanıcı listesinin resmî veya eksiksiz olduğunu garanti etmez."
          }
        }
      },
      "uyarilar": {
        "tip": "array",
        "ogeTipi": "string",
        "mesajSablonlari": [
          "Bu tarih {takvimYili} takvim yılında, ancak {isoYili} ISO yılındadır.",
          "Pazar başlangıçlı sayı POSIX %U konvansiyonudur; kanonik ISO sonucu değişmez.",
          "İş günü hesabında yalnız hafta sonları düşüldü; resmî tatiller dahil değildir.",
          "Listede {benzersizTatilSayisi} benzersiz tatil tarihi var; yalnız aralıktaki hafta içleri düşüldü ve listenin eksiksizliği doğrulanmaz."
        ]
      },
      "hata": {
        "tip": [
          "object",
          "null"
        ],
        "required": [
          "kod",
          "alan",
          "mesaj"
        ],
        "properties": {
          "kod": {
            "tip": "string"
          },
          "alan": {
            "tip": "string"
          },
          "mesaj": {
            "tip": "string"
          }
        }
      }
    }
  },
  "ornekDogrulama": {
    "hedef": "hesapla(ornekCagri[i].girdi)",
    "beklenen": "ornekCagri[i].beklenenOzet",
    "kural": "derin-kismi-eslesme",
    "nesneKurali": "Beklenen nesnenin her kendi alanı hedefte bulunmalı ve değeri aynı kuralla özyinelemeli eşleşmelidir; hedefteki fazla alanlara izin verilir.",
    "diziKurali": "Beklenen ve hedef dizileri aynı uzunlukta olmalı; her öğe aynı sıradaki hedef öğeyle aynı kuralla özyinelemeli eşleşmelidir.",
    "ilkelKurali": "JSON ilkel değerleri tip ve değer bakımından Object.is ile eşit olmalıdır.",
    "hedefteFazlaAlan": "izinli"
  },
  "ornekCagri": [
    {
      "ad": "Temel örnek",
      "girdi": {
        "tarih": "2026-07-26"
      },
      "beklenenOzet": {
        "gunAdi": "Pazar",
        "isoGunNo": 7,
        "isoHafta": {
          "isoYil": 2026,
          "hafta": 30,
          "etiket": "2026-W30"
        },
        "yilinGunu": 207,
        "kalanGun": 158
      }
    },
    {
      "ad": "Yıl sınırı köşe vakası",
      "girdi": {
        "tarih": "2023-01-01"
      },
      "beklenenOzet": {
        "gunAdi": "Pazar",
        "isoHafta": {
          "isoYil": 2022,
          "hafta": 52,
          "etiket": "2022-W52"
        },
        "uyarilar": [
          "Bu tarih 2023 takvim yılında, ancak 2022 ISO yılındadır."
        ]
      }
    },
    {
      "ad": "İki tarih ve kullanıcı tatili",
      "girdi": {
        "tarih": "2026-01-01",
        "ikinciTarih": "2026-12-31",
        "haftaBaslangici": "pazar",
        "tatilGunleri": [
          "2026-04-23",
          "2026-05-01"
        ]
      },
      "beklenenOzet": {
        "fark": {
          "ikinciTarih": "2026-12-31",
          "gunFarki": 364,
          "haftaFarki": 52,
          "tamAyFarki": 11,
          "isGunu": 258,
          "resmiTatilDahilDegil": false
        },
        "uyarilar": [
          "Pazar başlangıçlı sayı POSIX %U konvansiyonudur; kanonik ISO sonucu değişmez.",
          "Listede 2 benzersiz tatil tarihi var; yalnız aralıktaki hafta içleri düşüldü ve listenin eksiksizliği doğrulanmaz."
        ]
      }
    },
    {
      "ad": "Geçersiz artık gün",
      "girdi": {
        "tarih": "2026-02-29"
      },
      "beklenenOzet": {
        "hata": {
          "kod": "GECERSIZ_TARIH",
          "alan": "tarih"
        }
      }
    }
  ],
  "formuller": {
    "utcIlkesi": "t = Date.UTC(y, m - 1, d); gün farkı = (t2 - t1) / 86400000. Yerel saat ve tarih string ayrıştırması kullanılmaz.",
    "isoHafta": "function isoHafta(y, m, d) {\n  const GUN = 86400000;\n  const t = Date.UTC(y, m - 1, d);\n  const gun = (new Date(t).getUTCDay() + 6) % 7;\n  const persembe = t + (3 - gun) * GUN;\n  const isoYil = new Date(persembe).getUTCFullYear();\n  const ocak1 = Date.UTC(isoYil, 0, 1);\n  const hafta = Math.floor((persembe - ocak1) / (7 * GUN)) + 1;\n  return { isoYil, hafta };\n}",
    "isoEtiket": "isoYil + '-W' + hafta.toString().padStart(2, '0')",
    "yilinGunu": "(Date.UTC(y,m-1,d) - Date.UTC(y,0,1)) / 86400000 + 1",
    "artikYil": "(y % 4 === 0 && y % 100 !== 0) || y % 400 === 0",
    "yildakiGunSayisi": "artikYil ? 366 : 365",
    "kalanGun": "yildakiGunSayisi - yilinGunu",
    "yilinYuzdesi": "round(yilinGunu / yildakiGunSayisi * 100, 2)",
    "ceyrek": "Math.floor((m - 1) / 3) + 1",
    "isoGunNo": "((getUTCDay() + 6) % 7) + 1",
    "ayinKacinciHaftasi": "Math.floor((d - 1 + (ayinIlkGunuISOGunNo - 1)) / 7) + 1",
    "ayinKacinciHaftasiNotu": "[KAYNAK-DOĞRULANMADI] Bu özel formül evrensel standart değildir; Pazartesi–Pazar satırı ve ilk kısmi satır=1 ürün kararıdır.",
    "yildakiISOHaftaSayisi": "1 Ocak Perşembe ise veya artık yılda 1 Ocak Çarşamba ise 53; aksi halde 52.",
    "haftaPazarBaslangicli": "POSIX %U: ilkPazarOffset=(7-Jan1.getUTCDay())%7; ordinal<=offset ? 0 : floor((ordinal-offset-1)/7)+1.",
    "gunFarki": "(Date.UTC(y2,m2-1,d2) - Date.UTC(y1,m1-1,d1)) / 86400000",
    "haftaFarki": "round(gunFarki / 7, 1)",
    "tamAyFarki": "n=(y2-y1)*12+(m2-m1); n>0 ve d2<d1 ise n--; n<0 ve d2>d1 ise n++.",
    "isGunu": "Kronolojik (minT,maxT] aralığında Pzt–Cum; benzersiz kullanıcı tatilleri düşülür; sonuç sign(t2-t1) ile işaretlenir."
  },
  "kaynaklar": [
    {
      "kalem": "ISO standardı",
      "baslik": "ISO 8601-1:2019 — Date and time — Part 1: Basic rules",
      "url": "https://www.iso.org/standard/70907.html",
      "dogrulanan": "ISO 8601-1:2019 temel sürümü 2024'te teyit edilmiştir ve günceldir; resmî katalogda Amd 1:2022 mevcuttur.",
      "amendment": {
        "baslik": "ISO 8601-1:2019/Amd 1:2022 — Amendment 1: Technical corrections",
        "url": "https://www.iso.org/standard/81801.html",
        "durum": "mevcut"
      }
    },
    {
      "kalem": "ISO hafta ve Pazar %U tanımları",
      "baslik": "The Open Group Base Specifications Issue 8 — strftime",
      "url": "https://pubs.opengroup.org/onlinepubs/9799919799/functions/strftime.html",
      "dogrulanan": "%V için Pazartesi/ilk Perşembe/4 Ocak; %U için ilk Pazar ve hafta 00."
    },
    {
      "kalem": "52/53 hafta eşiği",
      "baslik": "RFC 5545 — iCalendar, bölüm 3.3.10",
      "url": "https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.10",
      "dogrulanan": "53. hafta yalnız 1 Ocak Perşembe veya artık yılda 1 Ocak Çarşamba koşulunda."
    },
    {
      "kalem": "Gregoryen artık yıl",
      "baslik": "Leap Years — U.S. Naval Observatory",
      "url": "https://aa.usno.navy.mil/faq/leap_years",
      "dogrulanan": "4/100/400 bölünebilme kuralı; 1900 ve 2000 örnekleri."
    },
    {
      "kalem": "Ay haftası konvansiyonlarının değişkenliği",
      "baslik": "Java WeekFields",
      "url": "https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/temporal/WeekFields.html",
      "dogrulanan": "Hafta alanının ilk gün ve asgari gün parametrelerine bağlı olduğu."
    },
    {
      "kalem": "Bölgesel hafta verisi",
      "baslik": "Unicode LDML Part 4 — Week Data",
      "url": "https://www.unicode.org/reports/tr35/tr35-dates.html#Week_Data",
      "dogrulanan": "firstDay ve minDays değerlerinin bölgeye göre değiştiği."
    },
    {
      "kalem": "Türkiye resmî tatilleri",
      "baslik": "2429 sayılı Ulusal Bayram ve Genel Tatiller Hakkında Kanun",
      "url": "https://www.mevzuat.gov.tr/MevzuatMetin/1.5.2429.pdf",
      "dogrulanan": "Tatil günlerinin yasal düzenlemeye tabi olduğu."
    },
    {
      "kalem": "Yıllık dinî günler",
      "baslik": "T.C. Diyanet İşleri Başkanlığı — 2025 Dinî Günler",
      "url": "https://vakithesaplama.diyanet.gov.tr/dinigunler.php?yil=2025",
      "dogrulanan": "Dinî günlerin 2025 Miladi karşılıkları; 2026 listesiyle yıllar arası farkı gösterir."
    },
    {
      "kalem": "Yıllık dinî günler",
      "baslik": "T.C. Diyanet İşleri Başkanlığı — 2026 Dinî Günler",
      "url": "https://vakithesaplama.diyanet.gov.tr/dinigunler.php?yil=2026",
      "dogrulanan": "Dinî günlerin 2026 Miladi karşılıkları; 2025 listesiyle yıllar arası farkı gösterir."
    }
  ],
  "sinirlar": [
    "Resmî tatil bilmez ve resmî/eksiksiz tatil listesi iddiasında bulunmaz; yalnız kullanıcı girdisini uygular.",
    "Hicri veya Rumi takvim çevirmez.",
    "1583 öncesi Jülyen tarihleri ve tarihsel takvim geçişleri kapsam dışıdır.",
    "Saat, dakika, saniye veya saat dilimi çevirisi işlemez.",
    "ayinKacinciHaftasi ISO alanı değildir; belgelenmiş ürün konvansiyonudur.",
    "Pazar başlangıçlı sayı POSIX %U konvansiyonudur; evrensel ABD standardı veya ISO değildir.",
    "tamAyFarki gün bileşeni düzeltmesini kullanır; ay sonunu otomatik olarak ay dönümü saymaz."
  ]
}
