/* 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 . */ 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; /** *

Monatsnamen

* *

z.B. * * String nameTischri = HebraeischerKalender.monatsnamen[HebraeischerKalender.TISCHRI]; *

*/ 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)); } }