/** * Namens- und Pfadregeln der gefuehrten Rotation (#023). Rein, damit testbar. */ const NAME_SUFFIX = /\s*\(rotiert \d{2}\.\d{2}\.\d{4}\)$/; const PFAD_SUFFIX = /-r\d{8}(?:-\d+)?$/; /** TT.MM.JJJJ und JJJJMMTT nach dem Kalender in Berlin. */ export function rotationsDatum(jetzt: Date = new Date()): { anzeige: string; kompakt: string } { const [jahr, monat, tag] = new Intl.DateTimeFormat("en-CA", { timeZone: "Europe/Berlin" }) .format(jetzt) .split("-"); return { anzeige: `${tag}.${monat}.${jahr}`, kompakt: `${jahr}${monat}${tag}` }; } /** * „Backup A → B (rotiert 12.10.2026)“ – ein frueheres Rotations-Suffix wird ersetzt, damit * die Namen bei jeder Rotation nicht laenger werden. */ export function rotationsName(name: string, datum: string, maxLaenge = 200): string { const suffix = ` (rotiert ${datum})`; const basis = name.replace(NAME_SUFFIX, "").trim(); return `${basis.slice(0, Math.max(1, maxLaenge - suffix.length))}${suffix}`; } /** * Neuer Pfad fuer den Private Key des Nachfolgers: gleicher Name mit `-rJJJJMMTT`. Ein alter * Suffix wird ersetzt; ist der Pfad (auch durch eine fruehere, entfernte Zuweisung) belegt, * kommt eine laufende Nummer dazu. Zwei Dateien nebeneinander sind gewollt: bis der Nachfolger * getestet ist, bleibt der alte Schluessel benutzbar. */ export function rotationsPfad(pfad: string, datumKompakt: string, belegt: ReadonlySet): string { const basis = pfad.replace(PFAD_SUFFIX, ""); let kandidat = `${basis}-r${datumKompakt}`; for (let nummer = 2; belegt.has(kandidat); nummer += 1) kandidat = `${basis}-r${datumKompakt}-${nummer}`; return kandidat; }