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 |
} |