Bestimmung der Zeitpunkte von Ereignissen
ulrich
2023-03-23 d20d989f5495492f1258c8313db7c19b429111a3
commit | author | age
66d68b 1 /*
U 2   Zeitrechnung - a class library to determine calendar events
3   Copyright (c) 1984-2023 Ulrich Hilger, http://uhilger.de
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU Affero General Public License as published by
7   the Free Software Foundation, either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU Affero General Public License for more details.
14
15   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package de.uhilger.zeitrechnung.kalender;
19
20 import de.uhilger.zeitrechnung.Datum;
21 import de.uhilger.zeitrechnung.Definition;
22
23 /**
24  * Die Klasse HebraeischerKalender dient zu Umwandlung von generischem 
25  * Datum zu hebraeischem Datum und umgekehrt.
26  * 
27  * @author Ulrich Hilger
28  */
29 public class HebraeischerKalender extends BasisKalender implements Wandler {
30
31   public static final int NISAN = 1;
32   public static final int IYYAR = 2;
33   public static final int SIVAN = 3;
34   public static final int TAMMUZ = 4;
35   public static final int AV = 5;
36   public static final int ELUL = 6;
37   public static final int TISCHRI = 7;
38   public static final int MARESHVAN = 8;
39   public static final int KISLEV = 9;
40   public static final int TEVET = 10;
41   public static final int SHEVAT = 11;
42   public static final int ADAR = 12;
43   public static final int ADAR2 = 13;
44
45   /**
46    * <p>Monatsnamen</p>
47    * 
48    * <p>z.B. 
49    * <code>
50    * String nameTischri = HebraeischerKalender.monatsnamen[HebraeischerKalender.TISCHRI];
51    * </code></p>
52    */
53     public static final String[] monatsnamen = new String[] {
54         "Nisan",
55         "Iyyar",
56         "Sivan",
57         "Tammuz",
58         "Av",
59         "Elul",
60         "Tishri",
61         "Marheshvan",
62         "Kislev",
63         "Tevet",
64         "Shevat",
65         "Adar",
66         "Adar 2"};
67   
68   /**
69    * Das generische Datum des Starttages des hebraeischen Kalenders 
70    * wird im Konstruktor gesetzt.
71    */
72     private final long STARTTAG;  
73           
74   /**
75    * Ein Objekt der Klasse HebraeischerKalender erzeugen
76    * 
77    * Der hebraeische Kalender beginnt mit 1 Tischri 1 anno mundi (A.M.). 
78    * Historiker datieren diesen Tag mit Montag 7. September -3760 des 
79    * gregorianischen Kalenders (3761 v. u. Z.), was 
80    * gleichbedeutend ist mit dem 7. Oktober 3761 v.u.Z. (vor unserer 
81    * Zeit; engl. bce, before common era) des julianischen 
82    * Kalenders. Der Datumswechsel vollzieht sich im julianischen und 
83    * gregorianischen Kalender um Mitternacht, weshalb nach hebraeischer 
84    * Tageszaehlung unter Beruecksichtigung des Datumswechsels am Vorabend 
85    * bereits der 7. Oktober des julianischen bzw. der 7. September des 
86    * gregorianischen Kalenders begonnen hatte.
87    */
88   public HebraeischerKalender() {
89     super();
90     JulianischerKalender j = new JulianischerKalender();
91     STARTTAG = j.zuTagen(j.BCE(3761), Definition.OKTOBER, 7);
92   }
93   
94   /* ------- Schnittstelle Wandler -------------- */
95
96   /**
97    * Die Anzahl der Tage ermitteln, die zwischen einem gegebenen Datum 
98    * des hebraeischen Kalendersystems und dem Tag liegen, der im
99    * Gregorianischen Kalender mit dem Datum 1. Januar 1 bezeichnet ist.
100    * 
101    * @param jahr das Jahr im hebraeischen Kalendersystem
102    * @param monat der Monat im hebraeischen Kalendersystem
103    * @param tag der Tag im hebraeischen Kalendersysem
104    * 
105    * @return Anzahl Tage, die zwischen dem gegebenen Datum 
106    * und dem Tag liegen, der im 
107    * Gregorianischen Kalender mit dem Datum 1. Januar 1 bezeichnet ist. 
108    * Liegt das gegebene Datum vor dem 1. Januar 1 (gregorianisch), wird 
109    * eine negative Zahl zurueckgegeben. 
110    */  
111   @Override
112   public long zuTagen(long jahr, int monat, int tag) {
113         long datum =
114             neujahr(jahr)
115             + tag - 1;
116         
117         if(monat < TISCHRI) {
118             for(int m = TISCHRI; m <= letzterMonatImJahr(jahr); ++m)
119                 datum += letzterTagImMonat(m, jahr);
120
121             for(int m = NISAN; m < monat; ++m)
122                 datum += letzterTagImMonat(m, jahr);
123
124         } else {
125             for(int m = TISCHRI; m < monat; ++m)
126                 datum += letzterTagImMonat(m, jahr);
127         }
128         
129         return datum;
130   }
131
132   /**
133    * Die Anzahl der Tage ermitteln, die zwischen einem gegebenen Datum 
134    * des hebraeischen Kalendersystems und dem Tag liegen, der im
135    * Gregorianischen Kalender mit dem Datum 1. Januar 1 bezeichnet ist.
136    * 
137    * @param hDatum das Datum im hebraeischen Kalendersystem
138    * 
139    * @return Anzahl Tage, die zwischen dem gegebenen Datum 
140    * und dem Tag liegen, der im 
141    * Gregorianischen Kalender mit dem Datum 1. Januar 1 bezeichnet ist. 
142    * Liegt das gegebene Datum vor dem 1. Januar 1 (gregorianisch), wird 
143    * eine negative Zahl zurueckgegeben. 
144    */      
145   @Override
146   public long zuTagen(Datum hDatum) {
147     return zuTagen(hDatum.getJahr(), hDatum.getMonat(), hDatum.getTag());
148   }
149
150   /**
151    * Das Datum im hebraeischen Kalendersystem fuer ein generisches Datum 
152    * ermitteln.
153    * 
154    * @param tage Anzahl der Tage zwischen 1. Januar 1 im gregorianischen 
155    * Kalender und dem Tag, dessen Datum im betreffenden Kalendersystem 
156    * ermittelt werden soll
157    * @return das Datum im hebraeischen Kalendersystem
158    */
159   @Override
160   public Datum vonTagen(long tage) {
161         long annaeherung = 1 + ganzzahlQuotient(tage - STARTTAG, 35975351d/98496);
162     
163     long jahr;
164         for(jahr = annaeherung - 1; neujahr(jahr) <= tage; ++jahr);
165         jahr--;
166
167     int monat;
168         int start = tage < zuTagen(jahr, 1, 1) ? TISCHRI : NISAN;
169         for(monat = start; !(tage <= zuTagen(jahr, monat, letzterTagImMonat(monat, jahr))); ++monat);
170
171         int tag = (int)(1 + tage - zuTagen(jahr, monat, 1));
172     return new Datum(jahr, monat, tag);
173   }
174   
175   /* ------ Besondere Tage des hebraeischen Kalenders ----- */ 
176   
177   /*
178   Die Feiertage sind hier noch vermischt mit unterschiedlichen Verschieberegeln. 
179   TODO: Diese noch in einen separaten Verschiebe-Mechanismus ueberfuehren
180   */
181   
182     public long passah(long isoJahr) {
183     ISOKalender w = new ISOKalender();
184         long hYear = isoJahr - w.jahrVonTagen(STARTTAG);
185         return zuTagen(hYear, NISAN, 15);
186     }
187   
188     public long purim(long isoJahr) {
189     ISOKalender w = new ISOKalender();
190         long hYear = isoJahr - w.jahrVonTagen(STARTTAG);
191         int lastMonth = letzterMonatImJahr(hYear);
192         return zuTagen(hYear, lastMonth, 14);
193     }
194
195     public long taAnitEsther(long isoJahr) {
196         long purimDate = purim(isoJahr);
197         return wochentagVonGenerisch(purimDate) == Definition.SONNTAG ? purimDate - 3 : purimDate - 1;
198     }
199     
200     public long tishahBeAv(long isoJahr) {
201     ISOKalender w = new ISOKalender();
202         long hYear = isoJahr - w.jahrVonTagen(STARTTAG);
203         long ninthOfAv = zuTagen(hYear, 5, 9);
204         return wochentagVonGenerisch(ninthOfAv) == Definition.SAMSTAG ? ninthOfAv + 1 : ninthOfAv;
205     }
206   
207     public long yomHaZikkaron(long isoJahr) {
208     ISOKalender w = new ISOKalender();
209         long hYear = isoJahr - w.jahrVonTagen(STARTTAG);
210         long iyar4 = zuTagen(hYear, 2, 4);
211         return Definition.MITTWOCH < wochentagVonGenerisch(iyar4) ? tagVor(iyar4, Definition.MITTWOCH) : iyar4;
212     }
213   
214   /* ------ Besonderheiten des hebraeischen Kalenders ----- */ 
215   
216     public long tageszaehlung(long hJahr) {
217         long monate = ganzzahlQuotient(235 * hJahr - 234, 19);
218         double teile = 12084 + 13753d * monate;
219         long day = 29 * monate + ganzzahlQuotient(teile, 25920);
220         return modulo(3 * (day + 1), 7) < 3 ? day + 1 : day;
221     }
222
223     public long neujahr(long hJahr) {
224         return STARTTAG
225             + tageszaehlung(hJahr)
226             + neujahrVerzug(hJahr);
227     }
228     
229     public int neujahrVerzug(long hJahr) {
230         long ny0 = tageszaehlung(hJahr - 1);
231         long ny1 = tageszaehlung(hJahr);
232         long ny2 = tageszaehlung(hJahr + 1);
233         if(ny2 - ny1 == 356)
234             return 2;
235         else if(ny1 - ny0 == 382)
236             return 1;
237         else
238             return 0;
239     }
240
241     public boolean schaltjahr(long hJahr) {
242         return modulo(1 + 7 * hJahr, 19) < 7;
243     }
244
245     public int letzterMonatImJahr(long hJahr) {
246         return schaltjahr(hJahr) ? 13 : 12;
247     }
248
249     public int letzterTagImMonat(int hMonat, long hJahr) {
250         return ( (hMonat == 2 || hMonat == 4 || hMonat == 6 || hMonat == 10 || hMonat == 13)
251             || (hMonat == 12 && !schaltjahr(hJahr))
252             || (hMonat == 8 && !marheshvanLang(hJahr))
253             || (hMonat == 9 && kislevKurz(hJahr)) ) ? 29 : 30;
254     }
255
256     public boolean marheshvanLang(long hJahr) {
257         int days = tageImJahr(hJahr);
258         return days == 355 || days == 385;
259     }
260
261     public boolean kislevKurz(long hJahr) {
262         int tage = tageImJahr(hJahr);
263         return tage == 353 || tage == 383;
264     }
265     
266     public int tageImJahr(long hYear) {
267         return (int)(neujahr(hYear + 1) - neujahr(hYear));
268     }
269 }