{"id":206,"date":"2026-03-05T09:09:06","date_gmt":"2026-03-05T09:09:06","guid":{"rendered":"https:\/\/kalenderwoche.info\/blog\/?page_id=206"},"modified":"2026-03-05T09:11:38","modified_gmt":"2026-03-05T09:11:38","slug":"jahresrechner","status":"publish","type":"page","link":"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/","title":{"rendered":"Jahresrechner"},"content":{"rendered":"\n<section id=\"tool__jahresrechner\" aria-label=\"Jahresrechner\">\n  <style>\n    #tool__jahresrechner{\n      --bg:#ffffff;\n      --surface:#f6f7f8;\n      --border:#d7dbe0;\n      --text:#111827;\n      --muted:#4b5563;\n      --danger:#b42318;\n      --ok:#14532d;\n      --ring:#2563eb;\n\n      font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, \"Apple Color Emoji\",\"Segoe UI Emoji\";\n      color:var(--text);\n    }\n    #tool__jahresrechner .jr-wrap{\n      max-width:720px;\n      margin:0 auto;\n      padding:16px 12px;\n    }\n    #tool__jahresrechner .jr-card{\n      background:var(--bg);\n      border:1px solid var(--border);\n      border-radius:14px;\n      padding:16px;\n    }\n    #tool__jahresrechner .jr-head{\n      display:flex;\n      align-items:flex-start;\n      justify-content:space-between;\n      gap:12px;\n      margin-bottom:12px;\n    }\n    #tool__jahresrechner h2{\n      margin:0;\n      font-size:1.35rem;\n      line-height:1.25;\n      letter-spacing:-0.01em;\n    }\n    #tool__jahresrechner .jr-sub{\n      margin:6px 0 0;\n      color:var(--muted);\n      font-size:0.98rem;\n      line-height:1.45;\n    }\n    #tool__jahresrechner .jr-grid{\n      display:grid;\n      grid-template-columns:1fr;\n      gap:12px;\n      margin-top:12px;\n    }\n    @media (min-width: 640px){\n      #tool__jahresrechner .jr-grid{\n        grid-template-columns:1fr 1fr;\n        gap:12px;\n      }\n    }\n    #tool__jahresrechner .jr-field{\n      display:flex;\n      flex-direction:column;\n      gap:6px;\n      min-width:0;\n    }\n    #tool__jahresrechner label{\n      font-size:0.95rem;\n      color:var(--text);\n      font-weight:600;\n    }\n    #tool__jahresrechner .jr-help{\n      color:var(--muted);\n      font-size:0.9rem;\n      line-height:1.35;\n      margin:0;\n    }\n    #tool__jahresrechner input[type=\"date\"],\n    #tool__jahresrechner input[type=\"number\"],\n    #tool__jahresrechner select{\n      width:100%;\n      border:1px solid var(--border);\n      border-radius:12px;\n      padding:10px 12px;\n      background:var(--surface);\n      color:var(--text);\n      font-size:1rem;\n      line-height:1.2;\n      min-height:44px;\n      box-sizing:border-box;\n    }\n    #tool__jahresrechner input[type=\"date\"]:focus,\n    #tool__jahresrechner input[type=\"number\"]:focus,\n    #tool__jahresrechner select:focus,\n    #tool__jahresrechner button:focus{\n      outline:3px solid rgba(37, 99, 235, 0.25);\n      outline-offset:2px;\n      border-color:var(--ring);\n    }\n    #tool__jahresrechner .jr-row{\n      display:flex;\n      flex-wrap:wrap;\n      gap:10px 12px;\n      align-items:center;\n      justify-content:space-between;\n      margin-top:12px;\n    }\n    #tool__jahresrechner .jr-actions{\n      display:flex;\n      flex-wrap:wrap;\n      gap:10px;\n      align-items:center;\n    }\n    #tool__jahresrechner .jr-btn{\n      appearance:none;\n      border:1px solid var(--border);\n      background:var(--surface);\n      color:var(--text);\n      border-radius:12px;\n      padding:10px 12px;\n      min-height:44px;\n      font-size:1rem;\n      line-height:1.2;\n      cursor:pointer;\n      user-select:none;\n    }\n    #tool__jahresrechner .jr-btn:hover{ border-color:#b8bec6; }\n    #tool__jahresrechner .jr-btn-primary{\n      background:#111827;\n      color:#fff;\n      border-color:#111827;\n    }\n    #tool__jahresrechner .jr-btn-primary:hover{ background:#0b1220; border-color:#0b1220; }\n    #tool__jahresrechner .jr-toggle{\n      display:flex;\n      align-items:flex-start;\n      gap:10px;\n      padding:10px 12px;\n      border:1px solid var(--border);\n      border-radius:12px;\n      background:var(--surface);\n    }\n    #tool__jahresrechner .jr-toggle input{\n      margin-top:3px;\n      width:18px;\n      height:18px;\n      flex:0 0 auto;\n    }\n    #tool__jahresrechner .jr-toggle strong{\n      display:block;\n      font-size:0.98rem;\n      line-height:1.25;\n    }\n    #tool__jahresrechner .jr-toggle span{\n      display:block;\n      color:var(--muted);\n      font-size:0.9rem;\n      line-height:1.35;\n      margin-top:2px;\n    }\n    #tool__jahresrechner .jr-msg{\n      margin-top:12px;\n      padding:10px 12px;\n      border-radius:12px;\n      border:1px solid var(--border);\n      background:var(--surface);\n      color:var(--muted);\n      font-size:0.95rem;\n      line-height:1.45;\n    }\n    #tool__jahresrechner .jr-msg[hidden]{ display:none; }\n    #tool__jahresrechner .jr-msg.jr-error{\n      border-color:rgba(180,35,24,0.35);\n      background:rgba(180,35,24,0.06);\n      color:var(--danger);\n    }\n    #tool__jahresrechner .jr-results{\n      margin-top:12px;\n      border:1px solid var(--border);\n      border-radius:14px;\n      overflow:hidden;\n    }\n    #tool__jahresrechner .jr-results-head{\n      display:flex;\n      align-items:center;\n      justify-content:space-between;\n      gap:10px;\n      padding:12px;\n      background:var(--surface);\n      border-bottom:1px solid var(--border);\n    }\n    #tool__jahresrechner .jr-results-head strong{\n      font-size:1rem;\n      line-height:1.25;\n    }\n    #tool__jahresrechner .jr-copyhint{\n      color:var(--muted);\n      font-size:0.9rem;\n      line-height:1.25;\n      margin-left:auto;\n      white-space:nowrap;\n    }\n    #tool__jahresrechner .jr-table{\n      width:100%;\n      border-collapse:separate;\n      border-spacing:0;\n      background:var(--bg);\n    }\n    #tool__jahresrechner .jr-table th,\n    #tool__jahresrechner .jr-table td{\n      padding:12px;\n      border-bottom:1px solid var(--border);\n      vertical-align:top;\n      text-align:left;\n      font-size:0.98rem;\n      line-height:1.35;\n    }\n    #tool__jahresrechner .jr-table th{\n      width:48%;\n      color:var(--muted);\n      font-weight:600;\n      background:linear-gradient(to bottom, rgba(246,247,248,0.55), rgba(246,247,248,0.0));\n    }\n    #tool__jahresrechner .jr-table tr:last-child th,\n    #tool__jahresrechner .jr-table tr:last-child td{\n      border-bottom:none;\n    }\n    #tool__jahresrechner .jr-note{\n      padding:12px;\n      border-top:1px solid var(--border);\n      background:var(--bg);\n      color:var(--muted);\n      font-size:0.92rem;\n      line-height:1.45;\n    }\n    #tool__jahresrechner .jr-content{\n      margin-top:14px;\n      padding:14px 2px 0;\n    }\n    #tool__jahresrechner .jr-content h3{\n      margin:0 0 8px;\n      font-size:1.1rem;\n      line-height:1.25;\n    }\n    #tool__jahresrechner .jr-content p{\n      margin:0 0 10px;\n      color:var(--muted);\n      line-height:1.6;\n    }\n    #tool__jahresrechner details{\n      border:1px solid var(--border);\n      border-radius:12px;\n      padding:10px 12px;\n      background:var(--surface);\n      margin-top:10px;\n    }\n    #tool__jahresrechner summary{\n      cursor:pointer;\n      font-weight:700;\n      color:var(--text);\n      outline:none;\n    }\n    #tool__jahresrechner details p{\n      margin:8px 0 0;\n      color:var(--muted);\n    }\n    #tool__jahresrechner .jr-sr{\n      position:absolute;\n      width:1px;\n      height:1px;\n      padding:0;\n      margin:-1px;\n      overflow:hidden;\n      clip:rect(0,0,0,0);\n      white-space:nowrap;\n      border:0;\n    }\n  <\/style>\n\n  <div class=\"jr-wrap\">\n    <div class=\"jr-card\">\n      <header class=\"jr-head\">\n        <div>\n          <h2>Jahresrechner<\/h2>\n          <p class=\"jr-sub\">Berechnen Sie Zeitspannen zwischen zwei Daten \u2013 als Jahre\/Monate\/Tage sowie als Gesamtwerte.<\/p>\n        <\/div>\n      <\/header>\n\n      <form class=\"jr-form\" novalidate>\n        <div class=\"jr-grid\">\n          <div class=\"jr-field\">\n            <label for=\"jr_start\">Startdatum<\/label>\n            <input id=\"jr_start\" name=\"start\" type=\"date\" required \/>\n            <p class=\"jr-help\">Pflichtfeld. Das Startdatum wird als erster Tag der Zeitspanne verwendet.<\/p>\n          <\/div>\n\n          <div class=\"jr-field\">\n            <label for=\"jr_end\">Enddatum<\/label>\n            <input id=\"jr_end\" name=\"end\" type=\"date\" required \/>\n            <p class=\"jr-help\">Pflichtfeld. Standard ist heute (lokal, ohne Zeitzonenverschiebung).<\/p>\n          <\/div>\n\n          <div class=\"jr-field\">\n            <label for=\"jr_mode\">Z\u00e4hlweise<\/label>\n            <select id=\"jr_mode\" name=\"mode\">\n              <option value=\"exclusive\">Exklusiv (Standard): Enddatum nicht mitz\u00e4hlen<\/option>\n              <option value=\"inclusive\">Inklusiv: beide Tage mitz\u00e4hlen<\/option>\n            <\/select>\n            <p class=\"jr-help\">Inklusiv ist sinnvoll f\u00fcr \u201evom \u2026 bis einschlie\u00dflich \u2026\u201c.<\/p>\n          <\/div>\n\n          <div class=\"jr-field\">\n            <label for=\"jr_round\">Wochen anzeigen als<\/label>\n            <select id=\"jr_round\" name=\"round\">\n              <option value=\"1\">eine Dezimalstelle<\/option>\n              <option value=\"0\">ganze Wochen (gerundet)<\/option>\n              <option value=\"2\">zwei Dezimalstellen<\/option>\n            <\/select>\n            <p class=\"jr-help\">Die Wochen basieren auf Gesamt-Tagen \u00f7 7.<\/p>\n          <\/div>\n        <\/div>\n\n        <div class=\"jr-row\">\n          <div class=\"jr-actions\">\n            <button type=\"submit\" class=\"jr-btn jr-btn-primary\" data-action=\"calc\">Berechnen<\/button>\n            <button type=\"button\" class=\"jr-btn\" data-action=\"reset\">Zur\u00fccksetzen<\/button>\n            <button type=\"button\" class=\"jr-btn\" data-action=\"copy\" aria-describedby=\"jr_copy_status\">Ergebnis kopieren<\/button>\n            <span id=\"jr_copy_status\" class=\"jr-sr\" aria-live=\"polite\"><\/span>\n          <\/div>\n\n          <label class=\"jr-toggle\" for=\"jr_save\">\n            <input id=\"jr_save\" name=\"save\" type=\"checkbox\" \/>\n            <span>\n              <strong>Eingaben merken<\/strong>\n              <span>Speichert Start\/Ende und Einstellungen lokal in Ihrem Browser. Sie k\u00f6nnen das jederzeit deaktivieren.<\/span>\n            <\/span>\n          <\/label>\n        <\/div>\n\n        <div id=\"jr_msg\" class=\"jr-msg\" aria-live=\"polite\" hidden><\/div>\n\n        <section class=\"jr-results\" aria-label=\"Ergebnis\" tabindex=\"-1\">\n          <div class=\"jr-results-head\">\n            <strong id=\"jr_result_title\">Ergebnis<\/strong>\n            <span class=\"jr-copyhint\" id=\"jr_result_hint\">Tipp: Enter berechnet \u2022 Esc setzt zur\u00fcck<\/span>\n          <\/div>\n\n          <table class=\"jr-table\" role=\"table\" aria-describedby=\"jr_note\">\n            <tbody>\n              <tr>\n                <th scope=\"row\">Kalenderdifferenz<\/th>\n                <td><span id=\"jr_out_ymd\">\u2014<\/span><\/td>\n              <\/tr>\n              <tr>\n                <th scope=\"row\">Vollendete Jahre<\/th>\n                <td><span id=\"jr_out_years\">\u2014<\/span><\/td>\n              <\/tr>\n              <tr>\n                <th scope=\"row\">Gesamt in Tagen<\/th>\n                <td><span id=\"jr_out_days\">\u2014<\/span><\/td>\n              <\/tr>\n              <tr>\n                <th scope=\"row\">Gesamt in Wochen<\/th>\n                <td><span id=\"jr_out_weeks\">\u2014<\/span><\/td>\n              <\/tr>\n              <tr>\n                <th scope=\"row\">Schaltjahre in der Spanne<\/th>\n                <td><span id=\"jr_out_leaps\">\u2014<\/span><\/td>\n              <\/tr>\n              <tr>\n                <th scope=\"row\">Hinweis<\/th>\n                <td><span id=\"jr_out_hint\">\u2014<\/span><\/td>\n              <\/tr>\n            <\/tbody>\n          <\/table>\n\n          <div class=\"jr-note\" id=\"jr_note\">\n            Die Kalenderdifferenz (Jahre\/Monate\/Tage) ist eine \u201emenschliche\u201c Aufteilung: zuerst Jahre, dann Monate, dann Resttage. Gesamtwerte werden \u00fcber Tagesz\u00e4hlung berechnet.\n          <\/div>\n        <\/section>\n      <\/form>\n\n      <div class=\"jr-content\">\n        <h3>Wof\u00fcr ist der Jahresrechner n\u00fctzlich?<\/h3>\n        <p>\n          Dieser Jahresrechner hilft Ihnen, eine Zeitspanne zwischen zwei Daten zuverl\u00e4ssig zu bestimmen \u2013 ohne Verwirrung durch\n          Monatsl\u00e4ngen, Schaltjahre oder Zeitzonen-Effekte. Sie erhalten zwei Sichtweisen: eine Kalenderdifferenz in Jahren, Monaten\n          und Tagen (vergleichbar mit einer Altersberechnung) sowie Gesamtwerte in Tagen und Wochen. Das ist praktisch, wenn Sie\n          Laufzeiten von Vertr\u00e4gen pr\u00fcfen, Projektzeitr\u00e4ume dokumentieren, Fristen grob in Wochen umrechnen oder nachvollziehen\n          m\u00f6chten, wie viele vollendete Jahre zwischen zwei Stichtagen liegen.\n        <\/p>\n        <p>\n          Die Eingaben werden lokal verarbeitet. Optional k\u00f6nnen Sie Ihre letzten Werte im Browser speichern, damit der Rechner beim\n          n\u00e4chsten Besuch sofort wieder einsatzbereit ist. Die Z\u00e4hlweise l\u00e4sst sich auf \u201einklusive\u201c umstellen, wenn beide Tage\n          ausdr\u00fccklich mitgez\u00e4hlt werden sollen (\u201ebis einschlie\u00dflich\u201c). Alle Ergebnisse werden im Format de-DE angezeigt.\n        <\/p>\n\n        <details>\n          <summary>Z\u00e4hlt das Enddatum mit?<\/summary>\n          <p>\n            Standardm\u00e4\u00dfig nicht (exklusiv). Wenn Sie \u201einklusive\u201c w\u00e4hlen, werden Start- und Enddatum beide mitgez\u00e4hlt. Das ist typisch\n            f\u00fcr Formulierungen wie \u201evom 1. bis einschlie\u00dflich 10.\u201c.\n          <\/p>\n        <\/details>\n        <details>\n          <summary>Warum unterscheiden sich Kalenderdifferenz und Gesamt-Tage?<\/summary>\n          <p>\n            Monate haben unterschiedlich viele Tage. Die Kalenderdifferenz teilt die Spanne in Jahre\/Monate\/Resttage auf. Die Gesamt-Tage\n            z\u00e4hlen dagegen jeden Tag in der Spanne \u2013 das ist die passende Basis f\u00fcr Wochen.\n          <\/p>\n        <\/details>\n        <details>\n          <summary>Wie werden Zeitzonen und Sommerzeit behandelt?<\/summary>\n          <p>\n            Die Berechnung arbeitet mit \u201elokalen\u201c Datumswerten ohne Uhrzeit und z\u00e4hlt Tage \u00fcber UTC-basierte Mitternacht. Dadurch bleiben\n            Ergebnisse stabil, auch wenn in der Spanne Sommerzeitwechsel liegen.\n          <\/p>\n        <\/details>\n        <details>\n          <summary>Was bedeutet \u201eSchaltjahre in der Spanne\u201c?<\/summary>\n          <p>\n            Gez\u00e4hlt werden Jahre, deren 29. Februar innerhalb Ihrer ausgew\u00e4hlten Zeitspanne liegt (unter Ber\u00fccksichtigung der Z\u00e4hlweise).\n            Das hilft, wenn Sie nachvollziehen m\u00f6chten, warum sich Tageszahlen \u00e4ndern.\n          <\/p>\n        <\/details>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <script>\n    (() => {\n      'use strict';\n\n      const ROOT = document.getElementById('tool__jahresrechner');\n      if (!ROOT) return;\n\n      const $ = (sel) => ROOT.querySelector(sel);\n\n      const els = {\n        form: $('.jr-form'),\n        start: $('#jr_start'),\n        end: $('#jr_end'),\n        mode: $('#jr_mode'),\n        round: $('#jr_round'),\n        save: $('#jr_save'),\n        msg: $('#jr_msg'),\n        results: ROOT.querySelector('.jr-results'),\n        copyStatus: $('#jr_copy_status'),\n        outYmd: $('#jr_out_ymd'),\n        outYears: $('#jr_out_years'),\n        outDays: $('#jr_out_days'),\n        outWeeks: $('#jr_out_weeks'),\n        outLeaps: $('#jr_out_leaps'),\n        outHint: $('#jr_out_hint')\n      };\n\n      const LS_KEY = 'tool__jahresrechner__v1';\n\n      const pad2 = (n) => String(n).padStart(2, '0');\n\n      const todayISO = () => {\n        const d = new Date();\n        const y = d.getFullYear();\n        const m = d.getMonth() + 1;\n        const day = d.getDate();\n        return `${y}-${pad2(m)}-${pad2(day)}`;\n      };\n\n      const isISODate = (s) => \/^\\d{4}-\\d{2}-\\d{2}$\/.test(String(s || ''));\n\n      const parseISOToLocalDate = (iso) => {\n        if (!isISODate(iso)) return null;\n        const parts = iso.split('-').map((v) => Number(v));\n        const y = parts[0], m = parts[1], d = parts[2];\n        if (!Number.isInteger(y) || !Number.isInteger(m) || !Number.isInteger(d)) return null;\n        if (m < 1 || m > 12) return null;\n        if (d < 1 || d > 31) return null;\n        const dt = new Date(y, m - 1, d);\n        if (dt.getFullYear() !== y || (dt.getMonth() + 1) !== m || dt.getDate() !== d) return null;\n        return dt;\n      };\n\n      const toUTCStamp = (localDate) => Date.UTC(localDate.getFullYear(), localDate.getMonth(), localDate.getDate());\n\n      const formatDateDE = (localDate) => {\n        try {\n          return new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: '2-digit', day: '2-digit' }).format(localDate);\n        } catch (_) {\n          const y = localDate.getFullYear();\n          const m = pad2(localDate.getMonth() + 1);\n          const d = pad2(localDate.getDate());\n          return `${d}.${m}.${y}`;\n        }\n      };\n\n      const formatIntDE = (n) => {\n        const safe = Number.isFinite(n) ? n : 0;\n        try { return new Intl.NumberFormat('de-DE').format(safe); } catch (_) { return String(safe); }\n      };\n\n      const formatFloatDE = (n, decimals) => {\n        const safe = Number.isFinite(n) ? n : 0;\n        const d = Math.min(6, Math.max(0, Number(decimals) || 0));\n        try {\n          return new Intl.NumberFormat('de-DE', { minimumFractionDigits: d, maximumFractionDigits: d }).format(safe);\n        } catch (_) {\n          return safe.toFixed(d);\n        }\n      };\n\n      const addMonthsClamped = (date, monthsToAdd) => {\n        const y = date.getFullYear();\n        const m = date.getMonth();\n        const d = date.getDate();\n\n        const targetMonthIndex = m + monthsToAdd;\n        const targetY = y + Math.floor(targetMonthIndex \/ 12);\n        const targetM = ((targetMonthIndex % 12) + 12) % 12;\n\n        const lastDay = new Date(targetY, targetM + 1, 0).getDate();\n        const clampedD = Math.min(d, lastDay);\n        return new Date(targetY, targetM, clampedD);\n      };\n\n      const compareYMD = (a, b) => {\n        const ay = a.getFullYear(), by = b.getFullYear();\n        if (ay !== by) return ay < by ? -1 : 1;\n        const am = a.getMonth(), bm = b.getMonth();\n        if (am !== bm) return am < bm ? -1 : 1;\n        const ad = a.getDate(), bd = b.getDate();\n        if (ad !== bd) return ad < bd ? -1 : 1;\n        return 0;\n      };\n\n      const diffTotalDays = (start, end, inclusive) => {\n        const a = toUTCStamp(start);\n        const b = toUTCStamp(end);\n        const base = Math.round((b - a) \/ 86400000);\n        const days = inclusive ? base + 1 : base;\n        return days;\n      };\n\n      const diffCalendarYMD = (start, end) => {\n        if (compareYMD(end, start) < 0) return { years: 0, months: 0, days: 0 };\n\n        let years = end.getFullYear() - start.getFullYear();\n\n        const endAnniv = new Date(end.getFullYear(), start.getMonth(), Math.min(start.getDate(), new Date(end.getFullYear(), start.getMonth() + 1, 0).getDate()));\n        if (compareYMD(end, endAnniv) < 0) years -= 1;\n\n        const afterYears = new Date(start.getFullYear() + years, start.getMonth(), Math.min(start.getDate(), new Date(start.getFullYear() + years, start.getMonth() + 1, 0).getDate()));\n\n        let months = (end.getFullYear() - afterYears.getFullYear()) * 12 + (end.getMonth() - afterYears.getMonth());\n        if (months < 0) months = 0;\n\n        const afterMonths = addMonthsClamped(afterYears, months);\n        if (compareYMD(end, afterMonths) < 0) {\n          months = Math.max(0, months - 1);\n        }\n\n        const afterMonths2 = addMonthsClamped(afterYears, months);\n        let days = diffTotalDays(afterMonths2, end, false);\n        if (days < 0) days = 0;\n\n        return { years, months, days };\n      };\n\n      const isLeapYear = (y) => (y % 4 === 0 && y % 100 !== 0) || (y % 400 === 0);\n\n      const countLeapDaysInRange = (start, end, inclusive) => {\n        if (compareYMD(end, start) < 0) return 0;\n\n        const startStamp = toUTCStamp(start);\n        const endStamp = toUTCStamp(end);\n        const endAdj = inclusive ? endStamp : (endStamp - 86400000);\n\n        if (endAdj < startStamp) return 0;\n\n        const startY = start.getFullYear();\n        const endY = end.getFullYear();\n\n        let count = 0;\n        for (let y = startY; y <= endY; y++) {\n          if (!isLeapYear(y)) continue;\n          const feb29 = new Date(y, 1, 29);\n          const s = toUTCStamp(feb29);\n          if (s >= startStamp && s <= endAdj) count++;\n        }\n        return count;\n      };\n\n      const validate = (state) => {\n        const errors = [];\n\n        const s = parseISOToLocalDate(state.startISO);\n        const e = parseISOToLocalDate(state.endISO);\n\n        if (!s) errors.push('Bitte geben Sie ein g\u00fcltiges Startdatum an.');\n        if (!e) errors.push('Bitte geben Sie ein g\u00fcltiges Enddatum an.');\n\n        if (s && e) {\n          if (compareYMD(e, s) < 0) errors.push('Das Enddatum muss am oder nach dem Startdatum liegen.');\n        }\n\n        return {\n          ok: errors.length === 0,\n          errors,\n          startDate: s,\n          endDate: e\n        };\n      };\n\n      const compute = (state) => {\n        const v = validate(state);\n        if (!v.ok) {\n          return { ok: false, errors: v.errors };\n        }\n\n        const inclusive = state.mode === 'inclusive';\n        const cal = diffCalendarYMD(v.startDate, v.endDate);\n        const days = diffTotalDays(v.startDate, v.endDate, inclusive);\n        const dec = Math.min(2, Math.max(0, Number(state.round) || 1));\n        const weeksRaw = days \/ 7;\n\n        const weeks = dec === 0 ? Math.round(weeksRaw) : Number(weeksRaw.toFixed(dec));\n        const leapCount = countLeapDaysInRange(v.startDate, v.endDate, inclusive);\n\n        const sameDay = compareYMD(v.startDate, v.endDate) === 0;\n        const hint = sameDay\n          ? (inclusive ? 'Start- und Enddatum sind identisch. Inklusiv ergibt das 1 Tag.' : 'Start- und Enddatum sind identisch. Exklusiv ergibt das 0 Tage.')\n          : (inclusive ? 'Inklusive Z\u00e4hlweise: Beide Tage werden mitgez\u00e4hlt.' : 'Exklusive Z\u00e4hlweise: Das Enddatum wird nicht mitgez\u00e4hlt.');\n\n        return {\n          ok: true,\n          startDate: v.startDate,\n          endDate: v.endDate,\n          inclusive,\n          calendar: cal,\n          days,\n          weeks,\n          weeksDecimals: dec,\n          leapCount,\n          hint\n        };\n      };\n\n      const getStateFromUI = () => ({\n        startISO: String(els.start.value || '').trim(),\n        endISO: String(els.end.value || '').trim(),\n        mode: String(els.mode.value || 'exclusive'),\n        round: String(els.round.value || '1'),\n        save: Boolean(els.save.checked)\n      });\n\n      const setMessage = (text, kind) => {\n        const has = Boolean(text);\n        if (!has) {\n          els.msg.textContent = '';\n          els.msg.className = 'jr-msg';\n          els.msg.hidden = true;\n          return;\n        }\n        els.msg.hidden = false;\n        els.msg.textContent = text;\n        els.msg.className = kind === 'error' ? 'jr-msg jr-error' : 'jr-msg';\n      };\n\n      const render = (model) => {\n        if (!model || !model.ok) {\n          els.outYmd.textContent = '\u2014';\n          els.outYears.textContent = '\u2014';\n          els.outDays.textContent = '\u2014';\n          els.outWeeks.textContent = '\u2014';\n          els.outLeaps.textContent = '\u2014';\n          els.outHint.textContent = '\u2014';\n          return;\n        }\n\n        const calStr = `${formatIntDE(model.calendar.years)} Jahr(e), ${formatIntDE(model.calendar.months)} Monat(e), ${formatIntDE(model.calendar.days)} Tag(e)`;\n        els.outYmd.textContent = calStr;\n\n        els.outYears.textContent = `${formatIntDE(model.calendar.years)} (vollendet)`;\n\n        els.outDays.textContent = `${formatIntDE(model.days)} Tag(e)`;\n\n        if (model.weeksDecimals === 0) {\n          els.outWeeks.textContent = `${formatIntDE(model.weeks)} Woche(n)`;\n        } else {\n          els.outWeeks.textContent = `${formatFloatDE(model.weeks, model.weeksDecimals)} Woche(n)`;\n        }\n\n        els.outLeaps.textContent = `${formatIntDE(model.leapCount)} (29. Februar innerhalb der Spanne)`;\n\n        const rangeLabel = `${formatDateDE(model.startDate)} \u2192 ${formatDateDE(model.endDate)}`;\n        els.outHint.textContent = `${model.hint} Zeitraum: ${rangeLabel}`;\n      };\n\n      const buildCopyText = (model) => {\n        if (!model || !model.ok) return '';\n        const range = `${formatDateDE(model.startDate)} bis ${formatDateDE(model.endDate)} (${model.inclusive ? 'inklusive' : 'exklusiv'})`;\n        const cal = `${formatIntDE(model.calendar.years)} Jahre, ${formatIntDE(model.calendar.months)} Monate, ${formatIntDE(model.calendar.days)} Tage`;\n        const days = `${formatIntDE(model.days)} Tage`;\n        const weeks = model.weeksDecimals === 0 ? `${formatIntDE(model.weeks)} Wochen` : `${formatFloatDE(model.weeks, model.weeksDecimals)} Wochen`;\n        const leaps = `${formatIntDE(model.leapCount)} Schaltjahr-Tag(e) (29.02.)`;\n        return `Jahresrechner \u2013 Ergebnis\\n${range}\\nKalenderdifferenz: ${cal}\\nVollendete Jahre: ${formatIntDE(model.calendar.years)}\\nGesamt: ${days} \/ ${weeks}\\nSchaltjahre in der Spanne: ${leaps}`;\n      };\n\n      const safeWriteLS = (state) => {\n        if (!state.save) {\n          try { localStorage.removeItem(LS_KEY); } catch (_) {}\n          return;\n        }\n        const payload = {\n          v: 1,\n          startISO: state.startISO,\n          endISO: state.endISO,\n          mode: state.mode,\n          round: state.round,\n          save: true\n        };\n        try { localStorage.setItem(LS_KEY, JSON.stringify(payload)); } catch (_) {}\n      };\n\n      const loadLS = () => {\n        try {\n          const raw = localStorage.getItem(LS_KEY);\n          if (!raw) return null;\n          const obj = JSON.parse(raw);\n          if (!obj || obj.v !== 1) return null;\n          return obj;\n        } catch (_) {\n          return null;\n        }\n      };\n\n      const applyUIState = (s) => {\n        if (!s) return;\n        if (typeof s.startISO === 'string') els.start.value = s.startISO;\n        if (typeof s.endISO === 'string') els.end.value = s.endISO;\n        if (typeof s.mode === 'string') els.mode.value = s.mode;\n        if (typeof s.round === 'string') els.round.value = s.round;\n        els.save.checked = Boolean(s.save);\n      };\n\n      const resetUI = () => {\n        els.start.value = '';\n        els.end.value = todayISO();\n        els.mode.value = 'exclusive';\n        els.round.value = '1';\n        els.save.checked = false;\n        setMessage('', '');\n        render({ ok: false });\n        try { localStorage.removeItem(LS_KEY); } catch (_) {}\n        els.results.focus({ preventScroll: true });\n      };\n\n      const run = () => {\n        const state = getStateFromUI();\n        const model = compute(state);\n\n        if (!model.ok) {\n          setMessage(model.errors.join(' '), 'error');\n          render({ ok: false });\n          return;\n        }\n\n        setMessage('', '');\n        render(model);\n        safeWriteLS(state);\n      };\n\n      const copyResult = async () => {\n        const state = getStateFromUI();\n        const model = compute(state);\n        if (!model.ok) {\n          setMessage('Bitte beheben Sie zuerst die Eingabefehler, bevor Sie das Ergebnis kopieren.', 'error');\n          return;\n        }\n        const text = buildCopyText(model);\n        if (!text) return;\n\n        const setCopyStatus = (t) => { els.copyStatus.textContent = t; };\n\n        try {\n          if (navigator && navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {\n            await navigator.clipboard.writeText(text);\n            setCopyStatus('Ergebnis wurde in die Zwischenablage kopiert.');\n            setMessage('Ergebnis kopiert.', '');\n          } else {\n            const ta = document.createElement('textarea');\n            ta.value = text;\n            ta.setAttribute('readonly', 'readonly');\n            ta.style.position = 'absolute';\n            ta.style.left = '-9999px';\n            ta.style.top = '0';\n            ROOT.appendChild(ta);\n            ta.select();\n            const ok = document.execCommand('copy');\n            ROOT.removeChild(ta);\n            if (ok) {\n              setCopyStatus('Ergebnis wurde in die Zwischenablage kopiert.');\n              setMessage('Ergebnis kopiert.', '');\n            } else {\n              setCopyStatus('Kopieren ist in diesem Browser nicht verf\u00fcgbar.');\n              setMessage('Kopieren ist in diesem Browser nicht verf\u00fcgbar. Markieren Sie das Ergebnis manuell.', 'error');\n            }\n          }\n        } catch (_) {\n          setCopyStatus('Kopieren ist fehlgeschlagen.');\n          setMessage('Kopieren ist fehlgeschlagen. Markieren Sie das Ergebnis manuell.', 'error');\n        }\n      };\n\n      const init = () => {\n        els.end.value = todayISO();\n\n        const saved = loadLS();\n        if (saved && saved.save) {\n          applyUIState(saved);\n        }\n\n        const state = getStateFromUI();\n        const model = compute(state);\n        if (model.ok) render(model);\n\n        els.form.addEventListener('submit', (e) => {\n          e.preventDefault();\n          run();\n          els.results.focus({ preventScroll: true });\n        });\n\n        ROOT.addEventListener('click', (e) => {\n          const btn = e.target && e.target.closest ? e.target.closest('button[data-action]') : null;\n          if (!btn) return;\n          const action = btn.getAttribute('data-action');\n          if (action === 'calc') {\n            run();\n            els.results.focus({ preventScroll: true });\n          } else if (action === 'reset') {\n            resetUI();\n          } else if (action === 'copy') {\n            copyResult();\n          }\n        });\n\n        const onChange = () => {\n          const s = getStateFromUI();\n          if (s.save) safeWriteLS(s);\n        };\n\n        els.start.addEventListener('change', onChange, { passive: true });\n        els.end.addEventListener('change', onChange, { passive: true });\n        els.mode.addEventListener('change', onChange, { passive: true });\n        els.round.addEventListener('change', onChange, { passive: true });\n        els.save.addEventListener('change', () => {\n          const s = getStateFromUI();\n          safeWriteLS(s);\n          if (!s.save) {\n            setMessage('Speichern deaktiviert. Vorherige Werte wurden gel\u00f6scht.', '');\n          } else {\n            setMessage('Speichern aktiviert. Ihre aktuellen Werte werden lokal gemerkt.', '');\n          }\n        }, { passive: true });\n\n        ROOT.addEventListener('keydown', (e) => {\n          const key = e.key;\n          if (key === 'Escape') {\n            const active = document.activeElement;\n            const inTool = active && ROOT.contains(active);\n            if (inTool) {\n              e.preventDefault();\n              resetUI();\n            }\n          }\n        });\n      };\n\n      init();\n    })();\n  <\/script>\n<\/section>\n","protected":false},"excerpt":{"rendered":"<p>Jahresrechner Berechnen Sie Zeitspannen zwischen zwei Daten \u2013 als Jahre\/Monate\/Tage sowie als Gesamtwerte. Startdatum Pflichtfeld. Das Startdatum wird als erster Tag der Zeitspanne verwendet. Enddatum Pflichtfeld. Standard ist heute (lokal, ohne Zeitzonenverschiebung). Z\u00e4hlweise Exklusiv (Standard): Enddatum nicht mitz\u00e4hlenInklusiv: beide Tage mitz\u00e4hlen Inklusiv ist sinnvoll f\u00fcr \u201evom \u2026 bis einschlie\u00dflich \u2026\u201c. Wochen anzeigen als eine Dezimalstelleganze &#8230; <a title=\"Jahresrechner\" class=\"read-more\" href=\"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/\" aria-label=\"Mehr Informationen \u00fcber Jahresrechner\">Weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-206","page","type-page","status-publish"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Jahre berechnen: Zeitspanne zwischen zwei Daten exakt ermitteln<\/title>\n<meta name=\"description\" content=\"Jahre berechnen zwischen zwei Daten: Kalenderdifferenz in Jahren\/Monaten\/Tagen plus Gesamtwerte in Tagen und Wochen. Lokal im Browser, optional speicherbar, inkl. Z\u00e4hlweise \u201ebis einschlie\u00dflich\u201c (de-DE).\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Jahre berechnen: Zeitspanne zwischen zwei Daten exakt ermitteln\" \/>\n<meta property=\"og:description\" content=\"Jahre berechnen zwischen zwei Daten: Kalenderdifferenz in Jahren\/Monaten\/Tagen plus Gesamtwerte in Tagen und Wochen. Lokal im Browser, optional speicherbar, inkl. Z\u00e4hlweise \u201ebis einschlie\u00dflich\u201c (de-DE).\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/\" \/>\n<meta property=\"og:site_name\" content=\"Kalender Wissen\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-05T09:11:38+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data1\" content=\"3\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/jahresrechner\\\/\",\"url\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/jahresrechner\\\/\",\"name\":\"Jahre berechnen: Zeitspanne zwischen zwei Daten exakt ermitteln\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/#website\"},\"datePublished\":\"2026-03-05T09:09:06+00:00\",\"dateModified\":\"2026-03-05T09:11:38+00:00\",\"description\":\"Jahre berechnen zwischen zwei Daten: Kalenderdifferenz in Jahren\\\/Monaten\\\/Tagen plus Gesamtwerte in Tagen und Wochen. Lokal im Browser, optional speicherbar, inkl. Z\u00e4hlweise \u201ebis einschlie\u00dflich\u201c (de-DE).\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/jahresrechner\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/jahresrechner\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/jahresrechner\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Start\",\"item\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Jahresrechner\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/\",\"name\":\"Kalenderwissen\",\"description\":\"f\u00fcr den Wissenshunger\",\"publisher\":{\"@id\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/#organization\",\"name\":\"Kalenderwissen\",\"url\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/02\\\/apple-touch-icon.png\",\"contentUrl\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/02\\\/apple-touch-icon.png\",\"width\":180,\"height\":180,\"caption\":\"Kalenderwissen\"},\"image\":{\"@id\":\"https:\\\/\\\/kalenderwoche.info\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Jahre berechnen: Zeitspanne zwischen zwei Daten exakt ermitteln","description":"Jahre berechnen zwischen zwei Daten: Kalenderdifferenz in Jahren\/Monaten\/Tagen plus Gesamtwerte in Tagen und Wochen. Lokal im Browser, optional speicherbar, inkl. Z\u00e4hlweise \u201ebis einschlie\u00dflich\u201c (de-DE).","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/","og_locale":"de_DE","og_type":"article","og_title":"Jahre berechnen: Zeitspanne zwischen zwei Daten exakt ermitteln","og_description":"Jahre berechnen zwischen zwei Daten: Kalenderdifferenz in Jahren\/Monaten\/Tagen plus Gesamtwerte in Tagen und Wochen. Lokal im Browser, optional speicherbar, inkl. Z\u00e4hlweise \u201ebis einschlie\u00dflich\u201c (de-DE).","og_url":"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/","og_site_name":"Kalender Wissen","article_modified_time":"2026-03-05T09:11:38+00:00","twitter_card":"summary_large_image","twitter_misc":{"Gesch\u00e4tzte Lesezeit":"3\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/","url":"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/","name":"Jahre berechnen: Zeitspanne zwischen zwei Daten exakt ermitteln","isPartOf":{"@id":"https:\/\/kalenderwoche.info\/blog\/#website"},"datePublished":"2026-03-05T09:09:06+00:00","dateModified":"2026-03-05T09:11:38+00:00","description":"Jahre berechnen zwischen zwei Daten: Kalenderdifferenz in Jahren\/Monaten\/Tagen plus Gesamtwerte in Tagen und Wochen. Lokal im Browser, optional speicherbar, inkl. Z\u00e4hlweise \u201ebis einschlie\u00dflich\u201c (de-DE).","breadcrumb":{"@id":"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kalenderwoche.info\/blog\/jahresrechner\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/kalenderwoche.info\/blog\/jahresrechner\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Start","item":"https:\/\/kalenderwoche.info\/blog\/"},{"@type":"ListItem","position":2,"name":"Jahresrechner"}]},{"@type":"WebSite","@id":"https:\/\/kalenderwoche.info\/blog\/#website","url":"https:\/\/kalenderwoche.info\/blog\/","name":"Kalenderwissen","description":"f\u00fcr den Wissenshunger","publisher":{"@id":"https:\/\/kalenderwoche.info\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kalenderwoche.info\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/kalenderwoche.info\/blog\/#organization","name":"Kalenderwissen","url":"https:\/\/kalenderwoche.info\/blog\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/kalenderwoche.info\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/kalenderwoche.info\/blog\/wp-content\/uploads\/2026\/02\/apple-touch-icon.png","contentUrl":"https:\/\/kalenderwoche.info\/blog\/wp-content\/uploads\/2026\/02\/apple-touch-icon.png","width":180,"height":180,"caption":"Kalenderwissen"},"image":{"@id":"https:\/\/kalenderwoche.info\/blog\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/kalenderwoche.info\/blog\/wp-json\/wp\/v2\/pages\/206","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kalenderwoche.info\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/kalenderwoche.info\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/kalenderwoche.info\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kalenderwoche.info\/blog\/wp-json\/wp\/v2\/comments?post=206"}],"version-history":[{"count":1,"href":"https:\/\/kalenderwoche.info\/blog\/wp-json\/wp\/v2\/pages\/206\/revisions"}],"predecessor-version":[{"id":207,"href":"https:\/\/kalenderwoche.info\/blog\/wp-json\/wp\/v2\/pages\/206\/revisions\/207"}],"wp:attachment":[{"href":"https:\/\/kalenderwoche.info\/blog\/wp-json\/wp\/v2\/media?parent=206"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}