/*
|
Zeitrechnung - a class library to determine calendar events
|
Copyright (c) 1984-2023 Ulrich Hilger, http://uhilger.de
|
|
This program is free software: you can redistribute it and/or modify
|
it under the terms of the GNU Affero General Public License as published by
|
the Free Software Foundation, either version 3 of the License, or
|
(at your option) any later version.
|
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU Affero General Public License for more details.
|
|
You should have received a copy of the GNU Affero General Public License
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
*/
|
package de.uhilger.zeitrechnung.kalender;
|
|
import de.uhilger.zeitrechnung.Datum;
|
import de.uhilger.zeitrechnung.Definition;
|
|
/**
|
* Die Klasse HebraeischerKalender dient zu Umwandlung von generischem
|
* Datum zu hebraeischem Datum und umgekehrt.
|
*
|
* @author Ulrich Hilger
|
*/
|
public class HebraeischerKalender extends BasisKalender implements Wandler {
|
|
public static final int NISAN = 1;
|
public static final int IYYAR = 2;
|
public static final int SIVAN = 3;
|
public static final int TAMMUZ = 4;
|
public static final int AV = 5;
|
public static final int ELUL = 6;
|
public static final int TISCHRI = 7;
|
public static final int MARESHVAN = 8;
|
public static final int KISLEV = 9;
|
public static final int TEVET = 10;
|
public static final int SHEVAT = 11;
|
public static final int ADAR = 12;
|
public static final int ADAR2 = 13;
|
|
/**
|
* <p>Monatsnamen</p>
|
*
|
* <p>z.B.
|
* <code>
|
* String nameTischri = HebraeischerKalender.monatsnamen[HebraeischerKalender.TISCHRI];
|
* </code></p>
|
*/
|
public static final String[] monatsnamen = new String[] {
|
"Nisan",
|
"Iyyar",
|
"Sivan",
|
"Tammuz",
|
"Av",
|
"Elul",
|
"Tishri",
|
"Marheshvan",
|
"Kislev",
|
"Tevet",
|
"Shevat",
|
"Adar",
|
"Adar 2"};
|
|
/**
|
* Das generische Datum des Starttages des hebraeischen Kalenders
|
* wird im Konstruktor gesetzt.
|
*/
|
private final long STARTTAG;
|
|
/**
|
* Ein Objekt der Klasse HebraeischerKalender erzeugen
|
*
|
* Der hebraeische Kalender beginnt mit 1 Tischri 1 anno mundi (A.M.).
|
* Historiker datieren diesen Tag mit Montag 7. September -3760 des
|
* gregorianischen Kalenders (3761 v. u. Z.), was
|
* gleichbedeutend ist mit dem 7. Oktober 3761 v.u.Z. (vor unserer
|
* Zeit; engl. bce, before common era) des julianischen
|
* Kalenders. Der Datumswechsel vollzieht sich im julianischen und
|
* gregorianischen Kalender um Mitternacht, weshalb nach hebraeischer
|
* Tageszaehlung unter Beruecksichtigung des Datumswechsels am Vorabend
|
* bereits der 7. Oktober des julianischen bzw. der 7. September des
|
* gregorianischen Kalenders begonnen hatte.
|
*/
|
public HebraeischerKalender() {
|
super();
|
JulianischerKalender j = new JulianischerKalender();
|
STARTTAG = j.zuTagen(j.BCE(3761), Definition.OKTOBER, 7);
|
}
|
|
/* ------- Schnittstelle Wandler -------------- */
|
|
/**
|
* Die Anzahl der Tage ermitteln, die zwischen einem gegebenen Datum
|
* des hebraeischen Kalendersystems und dem Tag liegen, der im
|
* Gregorianischen Kalender mit dem Datum 1. Januar 1 bezeichnet ist.
|
*
|
* @param jahr das Jahr im hebraeischen Kalendersystem
|
* @param monat der Monat im hebraeischen Kalendersystem
|
* @param tag der Tag im hebraeischen Kalendersysem
|
*
|
* @return Anzahl Tage, die zwischen dem gegebenen Datum
|
* und dem Tag liegen, der im
|
* Gregorianischen Kalender mit dem Datum 1. Januar 1 bezeichnet ist.
|
* Liegt das gegebene Datum vor dem 1. Januar 1 (gregorianisch), wird
|
* eine negative Zahl zurueckgegeben.
|
*/
|
@Override
|
public long zuTagen(long jahr, int monat, int tag) {
|
long datum =
|
neujahr(jahr)
|
+ tag - 1;
|
|
if(monat < TISCHRI) {
|
for(int m = TISCHRI; m <= letzterMonatImJahr(jahr); ++m)
|
datum += letzterTagImMonat(m, jahr);
|
|
for(int m = NISAN; m < monat; ++m)
|
datum += letzterTagImMonat(m, jahr);
|
|
} else {
|
for(int m = TISCHRI; m < monat; ++m)
|
datum += letzterTagImMonat(m, jahr);
|
}
|
|
return datum;
|
}
|
|
/**
|
* Die Anzahl der Tage ermitteln, die zwischen einem gegebenen Datum
|
* des hebraeischen Kalendersystems und dem Tag liegen, der im
|
* Gregorianischen Kalender mit dem Datum 1. Januar 1 bezeichnet ist.
|
*
|
* @param hDatum das Datum im hebraeischen Kalendersystem
|
*
|
* @return Anzahl Tage, die zwischen dem gegebenen Datum
|
* und dem Tag liegen, der im
|
* Gregorianischen Kalender mit dem Datum 1. Januar 1 bezeichnet ist.
|
* Liegt das gegebene Datum vor dem 1. Januar 1 (gregorianisch), wird
|
* eine negative Zahl zurueckgegeben.
|
*/
|
@Override
|
public long zuTagen(Datum hDatum) {
|
return zuTagen(hDatum.getJahr(), hDatum.getMonat(), hDatum.getTag());
|
}
|
|
/**
|
* Das Datum im hebraeischen Kalendersystem fuer ein generisches Datum
|
* ermitteln.
|
*
|
* @param tage Anzahl der Tage zwischen 1. Januar 1 im gregorianischen
|
* Kalender und dem Tag, dessen Datum im betreffenden Kalendersystem
|
* ermittelt werden soll
|
* @return das Datum im hebraeischen Kalendersystem
|
*/
|
@Override
|
public Datum vonTagen(long tage) {
|
long annaeherung = 1 + ganzzahlQuotient(tage - STARTTAG, 35975351d/98496);
|
|
long jahr;
|
for(jahr = annaeherung - 1; neujahr(jahr) <= tage; ++jahr);
|
jahr--;
|
|
int monat;
|
int start = tage < zuTagen(jahr, 1, 1) ? TISCHRI : NISAN;
|
for(monat = start; !(tage <= zuTagen(jahr, monat, letzterTagImMonat(monat, jahr))); ++monat);
|
|
int tag = (int)(1 + tage - zuTagen(jahr, monat, 1));
|
return new Datum(jahr, monat, tag);
|
}
|
|
/* ------ Besondere Tage des hebraeischen Kalenders ----- */
|
|
/*
|
Die Feiertage sind hier noch vermischt mit unterschiedlichen Verschieberegeln.
|
TODO: Diese noch in einen separaten Verschiebe-Mechanismus ueberfuehren
|
*/
|
|
public long passah(long isoJahr) {
|
ISOKalender w = new ISOKalender();
|
long hYear = isoJahr - w.jahrVonTagen(STARTTAG);
|
return zuTagen(hYear, NISAN, 15);
|
}
|
|
public long purim(long isoJahr) {
|
ISOKalender w = new ISOKalender();
|
long hYear = isoJahr - w.jahrVonTagen(STARTTAG);
|
int lastMonth = letzterMonatImJahr(hYear);
|
return zuTagen(hYear, lastMonth, 14);
|
}
|
|
public long taAnitEsther(long isoJahr) {
|
long purimDate = purim(isoJahr);
|
return wochentagVonGenerisch(purimDate) == Definition.SONNTAG ? purimDate - 3 : purimDate - 1;
|
}
|
|
public long tishahBeAv(long isoJahr) {
|
ISOKalender w = new ISOKalender();
|
long hYear = isoJahr - w.jahrVonTagen(STARTTAG);
|
long ninthOfAv = zuTagen(hYear, 5, 9);
|
return wochentagVonGenerisch(ninthOfAv) == Definition.SAMSTAG ? ninthOfAv + 1 : ninthOfAv;
|
}
|
|
public long yomHaZikkaron(long isoJahr) {
|
ISOKalender w = new ISOKalender();
|
long hYear = isoJahr - w.jahrVonTagen(STARTTAG);
|
long iyar4 = zuTagen(hYear, 2, 4);
|
return Definition.MITTWOCH < wochentagVonGenerisch(iyar4) ? tagVor(iyar4, Definition.MITTWOCH) : iyar4;
|
}
|
|
/* ------ Besonderheiten des hebraeischen Kalenders ----- */
|
|
public long tageszaehlung(long hJahr) {
|
long monate = ganzzahlQuotient(235 * hJahr - 234, 19);
|
double teile = 12084 + 13753d * monate;
|
long day = 29 * monate + ganzzahlQuotient(teile, 25920);
|
return modulo(3 * (day + 1), 7) < 3 ? day + 1 : day;
|
}
|
|
public long neujahr(long hJahr) {
|
return STARTTAG
|
+ tageszaehlung(hJahr)
|
+ neujahrVerzug(hJahr);
|
}
|
|
public int neujahrVerzug(long hJahr) {
|
long ny0 = tageszaehlung(hJahr - 1);
|
long ny1 = tageszaehlung(hJahr);
|
long ny2 = tageszaehlung(hJahr + 1);
|
if(ny2 - ny1 == 356)
|
return 2;
|
else if(ny1 - ny0 == 382)
|
return 1;
|
else
|
return 0;
|
}
|
|
public boolean schaltjahr(long hJahr) {
|
return modulo(1 + 7 * hJahr, 19) < 7;
|
}
|
|
public int letzterMonatImJahr(long hJahr) {
|
return schaltjahr(hJahr) ? 13 : 12;
|
}
|
|
public int letzterTagImMonat(int hMonat, long hJahr) {
|
return ( (hMonat == 2 || hMonat == 4 || hMonat == 6 || hMonat == 10 || hMonat == 13)
|
|| (hMonat == 12 && !schaltjahr(hJahr))
|
|| (hMonat == 8 && !marheshvanLang(hJahr))
|
|| (hMonat == 9 && kislevKurz(hJahr)) ) ? 29 : 30;
|
}
|
|
public boolean marheshvanLang(long hJahr) {
|
int days = tageImJahr(hJahr);
|
return days == 355 || days == 385;
|
}
|
|
public boolean kislevKurz(long hJahr) {
|
int tage = tageImJahr(hJahr);
|
return tage == 353 || tage == 383;
|
}
|
|
public int tageImJahr(long hYear) {
|
return (int)(neujahr(hYear + 1) - neujahr(hYear));
|
}
|
}
|