Alle Jahre wieder - Berechnung beweglicher Feiertage
Programmierung
Geschrieben von: Peter Scholze   
Mittwoch, den 09. Februar 2011 um 22:35 Uhr

Jedes Jahr pünktlich -und für viele doch überraschend- steht Weihnachten vor der Tür - ein Fest, welches den gemeinen Programmierer nicht allein wegen der damit einhergehenden arbeitsfreien Feiertage erfreut, sondern nicht zuletzt auch wegen deren simpler Vorhersagbarkeit.

Schwieriger wird es da schon bei den sog. beweglichen Feiertagen wie Ostern, Pfingsten, Christi Himmelfahrt und Fronleichnam, deren Termine sich von Jahr zu Jahr ändern. Essentiell für die Bestimmung ist hier der Ostersonntag, von dem sich die anderen genannten Feste bzw. Feiertage ableiten lassen.

Nichts einfacher als das, sollte man denken, ist doch der Ostersonntag bereits seit dem Konzil von Nicaea (325 n.Chr.) eindeutig festgelegt auf den ersten Sonntag nach dem Frühlingsvollmond. Die in der Vergangenheit mit der Berechnung der Ostertermine und der abhängigen kirchlichen Feste befassten Menschen nannte man Komputisten, und im Gegensatz zu unseren modernen Computern konnten diese mit der kirchenamtlichen Osterdefinition auch etwas anfangen ... 

Den ehrenwerten Berufsstand der Komputisten machte schließlich der deutsche Mathematiker Carl Friedrich Gauss brotlos, indem er eine Osterformel entwickelte, deren endgültige Fassung im Jahre 1816 veröffentlicht wurde. Diese Gauss'sche Osterformel ist aufgrund der darin behandelten Ausnahmen eigentlich keine Formel, sondern ein Algorithmus, den Heiner Lichtenberg dann 1997 in eine wirkliche Formel gegossen hat1.

Die Osterberechnung nach Lichtenberg ist die Grundlage der folgenden kleinen Utility-Klasse in Java, die überall dort zur Anwendung kommen kann, wo die Berechnung von Arbeitstagen oder Börsen- bzw. Banktagen von Belang ist:

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
 
public class MovableFeastsUtil {
 
    private static Calendar getGaussianEaster(int year){
 
        int k = year / 100;
        int tmp = (3*k + 3) / 4;
        int m = 15 + tmp - (8*k +13)/25;
        int s = 2 - tmp;
        int a = year % 19;
        int d = (19*a + m)%30;
        int r = (d/29)+(d/28 - d/29) * (a / 11);
        int og = 21 + d - r;
        int sz = 7 - (year + year/4 + s)%7;
        int oe = 7 - (og - sz)%7;
        int os = og + oe - 1;
 
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, 1);
 
        cal.add(Calendar.DAY_OF_MONTH, os);
 
        return(cal);
    }
 
    public static Date getEastersunday(int year){
        return(getGaussianEaster(year).getTime());
    }
 
    public static Date getWhitsunday(int year){
        Calendar cal = getGaussianEaster(year);
        cal.add(Calendar.DAY_OF_MONTH, 49);
 
        return(cal.getTime());
    }
 
    public static Date getCorpusChristi(int year){
        Calendar cal = getGaussianEaster(year);
        cal.add(Calendar.DAY_OF_MONTH, 60);
 
        return(cal.getTime());
    }
 
    public static Date getAscensionDay(int year){
        Calendar cal = getGaussianEaster(year);
        cal.add(Calendar.DAY_OF_MONTH, 39);
 
        return(cal.getTime());
    }
 
    public static void main(String[] args){
 
        System.out.println("Ostersonntag: "+getEastersunday(2011));
        System.out.println("Pfingstsonntag: "+getWhitsunday(2011));
        System.out.println("Christi Himmelfahrt: "+getAscensionDay(2011));
        System.out.println("Fronleichnam: "+getCorpusChristi(2011));
 
    }
}
 

Ein künftiger Artikel wird die Integration der MovableFeastsUtil-Klasse mit der objectlabkit-Library behandeln, die ihrerseits die Datumsrechnung unter Berücksichtigung von Feiertagen zum Gegenstand hat.

1H. Lichtenberg, Zur Interpretation der Gaußschen Osterformel und ihrer Ausnahmeregeln, Historia Mathematica 24,441 - 444 (1997)