Feiertag-Rechner, Indesign und „Häh…?“

29 Aug

Für komfortable Kalender-Kalkulation gibt es einige Formeln, die die beweglichen Feiertage für ein beliebiges Jahr ausrechnen. Mit Javascript geht das im Browser, und mit Javascript geht das auch in Adobe Indesign.

Allerdings hat Indesign hier eine Macke: Negative Monatszahlen (was im Browser wie erwartet funktioniert) ändern nicht die Jahreszahl. Wo also Date(2020,-1,1) eigentlich den 1. Dezember 2019 ergeben sollte, liefert Indesign hier den 1. Dezember 2020. Was dann auch erklärte, warum mein Kalender-Generator die Wochentage der Vormonate zum jeweiligen Jahr immer falsch machte …

Na gut, wenn man’s weiß, kann man ja vorher die Umrechnung von Hand machen.

Dann begann der Fasching zu wandern: wenn ich die 45 Tage vor Ostersonntag verwendete, um den Aschermittwoch in den Kalender zu zeichnen, gab es alle paar Jahre einen Ascherdonnerstag. Und einen Rosendienstag. Und einen Faschingsmittwoch. Auch im Browser, nicht nur in Indesign.

Und nein, das hat nichts mit Schaltjahr zu tun. Hier scheint es sich eher um einen Rundungsfehler zu handeln, wenn die Millisekunden subtrahiert werden. Das wiederum ließ sich beheben, in dem ich statt 45 Tagen nun 45,1 Tage in die Formel setzte. Seitdem passt auch der Fasching wieder.

	/**
	 * 
	 * Berechne Feiertage eines Jahres (Deutschland, kath.)
	 * und setze sie ins Objekt ftali ein
	 * Schlüssel: i2017-01-02 ( "i" + ISO-Datum ) für Feiertage
	 * t2020-01-01 für teilw. Feiertage (bundesuneinheitlich)
	 * z2020-02-03 für nicht-Feiertage aber Textanmerkung (z.B. Fastnacht)
	 * @param {int} jahr
	 * @param {object} ftali
	 * @returns {undefined}
	 */
	this.feiertage_rechner = function ( jahr, ftali ) {

		function diso( dob ) {
			var jm = dob.getMonth();
			var d = dob.getDate();
			return dob.getFullYear()
					+ '-' + ( '00' + ( jm + 1 ).toString() ).slice(-2)
					+ '-' + ( '00' + dob.getDate().toString() ).slice(-2);
		}

		var doff = 24 * 60 * 60 * 1000;

		/*
		 * Osterkalkulation
		 */

		// Determines the date of Easter Sunday for a given year.
		// See: http://javascript.about.com/library/bleaster1.htm

		var a = jahr % 19;
		var b = Math.floor( jahr / 100 );
		var c = jahr % 100;
		var h = ( 19 * a + b - Math.floor( b / 4 ) - Math.floor( ( b - Math.floor( ( b + 8 ) / 25 ) + 1 ) / 3 ) + 15 ) % 30;
		var k = ( 32 + 2 * ( b % 4 ) + 2 * Math.floor( c / 4 ) - h - c % 4 ) % 7;
		var m = Math.floor( ( a + 11 * h + 22 * k ) / 451 );
		var month = Math.floor( ( h + k - 7 * m + 114 ) / 31 );
		var day = ( ( h + k - 7 * m + 114 ) % 31 ) + 1;
		var ostersonntag = new Date( jahr, month - 1, day, 0, 0, 0 );


		/*
		 *  Adventkalkulation
		 *  Das Kirchenjahr beginnt mit dem ersten Sonntag im Advent. 
		 *  Es gibt vier Adventssonntage. Der 4. Advent ist der letzte Sonntag vor dem 1. Weihnachtstag.
		 *  Daraus ergibt sich: Der 1. Advent ist der erste Sonntag nach dem 26.11.
		 *  (www.kirche-bremen.de)
		 *  
		 *  Buß- und Bettag ist 11 Tage vor dem 1. Adventssonntag
		 *  
		 */
		var basis = new Date( Date.UTC( jahr, 11 - 1, 26 ) );
		var adventTS = basis.valueOf() + ( doff * ( 7 - basis.getDay() ) );

		/*
		 * Statische Feiertage (i), teilw. (t), Zusatztage (z)
		 */

		ftali[ 'i' + jahr.toString() + '-01-01' ] = 'Neujahr';
		ftali[ 't' + jahr.toString() + '-01-06' ] = 'Hl. 3 Könige'; // teilw.
		ftali[ 'i' + jahr.toString() + '-05-01' ] = 'Tag d. Arbeit';
		ftali[ 't' + jahr.toString() + '-08-15' ] = 'Maria Himmelf.'; // teilw.
		ftali[ 'i' + jahr.toString() + '-10-03' ] = 'Tag d. Dt. Einheit';
		ftali[ 't' + jahr.toString() + '-10-31' ] = 'Reformationstag'; // Reformationstag (ev., teilw.)
		ftali[ 't' + jahr.toString() + '-11-01' ] = 'Allerheiligen'; // Allerheiligen (kath., teilw.)
		ftali[ 'z' + jahr.toString() + '-12-24' ] = 'Hl. Abend'; // 
		ftali[ 'i' + jahr.toString() + '-12-25' ] = '1. Weihnachtstag';
		ftali[ 'i' + jahr.toString() + '-12-26' ] = '2. Weihnachtstag';

		/*
		 * Oster-relative Tage rechnen
		 */

		ftali[ 'i' + diso( ostersonntag ) ] = 'Ostersonntag';
		ftali[ 'i' + diso( new Date( ostersonntag.valueOf( ) + 1 * doff ) )] = 'Ostermontag';
		ftali[ 'i' + diso( new Date( ostersonntag.valueOf( ) - 2 * doff ) )] = 'Karfreitag';
		ftali[ 'i' + diso( new Date( ostersonntag.valueOf( ) + 39 * doff ) )] = 'Chr. Himmelfahrt';
		ftali[ 'i' + diso( new Date( ostersonntag.valueOf( ) + 49 * doff ) )] = 'Pfingstsonntag';
		ftali[ 'i' + diso( new Date( ostersonntag.valueOf( ) + 50 * doff ) )] = 'Pfingstmontag';
		ftali[ 'i' + diso( new Date( ostersonntag.valueOf( ) + 60 * doff ) )] = 'Fronleichnam';

		// zusätzliche Ostern-relative Tage, die nicht direkt Feiertage sind (Index = z )

		ftali[ 'z' + diso( new Date( ostersonntag.valueOf() - 45.1 * doff ) ) ] = "Aschermittwoch";
		ftali[ 'z' + diso( new Date( ostersonntag.valueOf() - 46.1 * doff ) )] = "Faschingsdienstag";
		ftali[ 'z' + diso( new Date( ostersonntag.valueOf() - 47.1 * doff ) )] = "Rosenmontag";

		/*
		 * Advent-relative Tage rechnen
		 */

		ftali['i' + diso( new Date( adventTS ) )] = "1. Advent";
		ftali['i' + diso( new Date( adventTS + 7 * doff ) )] = "2. Advent";
		ftali['i' + diso( new Date( adventTS + 14 * doff ) )] = "3. Advent";
		ftali['i' + diso( new Date( adventTS + 21 * doff ) )] = "4. Advent";
		ftali['t' + diso( new Date( adventTS - 11 * doff ) )] = "Buß- und Bettag";
		ftali['i' + diso( new Date( adventTS - 7 * doff ) )] = "Totensonntag";

	};

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

drei × 5 =