Updated 2018-04-03 09:07:48 by dbohdan

JMeh 2018-04-03: This is a small algorithm for calculating German holidays. The basis is that all Catholic holidays depend on the date of Easter Sunday. The formula for calculating Easter Sunday was developed by German mathematician Carl Friedrich Gauss in 1800. Heiner Lichtenberg corrected this formula in 1997 and thus made the exemptions to the Gauss formula unnecessary.
proc Feiertage {y} {
  set defs {
    Neujahr                     01.01.
    Karfreitag                  -2
    Ostersonntag                +0
    Ostermontag                 +1
    {Erster Mai}                01.05.
    {Christi Himmelfahrt}       +39
    Pfingstmontag               +50
    Fronleichnam                +60
    {Tag der deutschen Einheit} 03.10.
    Allerheiligen               01.11.
    {Erster Weihnachtstag}      25.12.
    {Zweiter Weihnachtstag}     26.12.
  }
  
  # Lichtenberg-Formel (korrigierte Gauss-Formel) zur Berechnung des Ostersonntags (Offset zum 1. März):
  set a  [expr {$y % 19}]                                       ;# Mondparameter
  set k  [expr {$y / 100}]                                      ;# Säkularzahl
  set m  [expr {15 + (3 * $k + 3) / 4 - (8 * $k + 13) / 25}]    ;# säkulare Mondschaltung
  set d  [expr {(19 * $a + $m) % 30}]                           ;# Keim für den ersten Vollmond im Frühling
  set s  [expr {2 - (3 * $k + 3) / 4}]                          ;# säkulare Sonnenschaltung
  set r  [expr {$d / 29 + ($d / 28 - $d / 29) * $a / 11}]       ;# kalendarische Korrekturgröße (beseitigt die Gaußschen Ausnahmeregeln)
  set og [expr {21 + $d - $r}]                                  ;# Ostergrenze (Märzdatum des Ostervollmonds)
  set sz [expr {7 - ($y + $y / 4 + $s) % 7}]                    ;# erster Sonntag im März
  set oe [expr {7 - ($og - $sz) % 7}]                           ;# Entfernung des Ostersonntag von der Ostergrenze in Tagen
  set o  [expr {$og + $oe - 1}]                                 ;# Datum des Ostersonntags als Märzdatum (32. März = 1. April usw.)

  set os [clock add [clock scan $y-03-01] $o days]

  set feiertage [dict create]
  dict for {name tag} $defs {
    if {[regexp {^[+\-]} $tag]} {
      dict set feiertage $name [clock format [clock add $os $tag days] -format %d.%m.%Y]
    } else {
      dict set feiertage $name $tag$y
    }
  }
  return $feiertage
}


set today [clock format [clock seconds] -format %d.%m.%Y]
set year  [string range $today end-3 end]
dict for {name day} [Feiertage $year] {
  puts "$name = $day"
  if {$day eq $today} {
    puts "Heute ist ein Feiertag!"
  }
}