Update Spanish translation
[gnumeric.git] / plugins / fn-hebrew-date / hdate_hdate.c
blob028b4990e9127a26bfda1d16527906de6081e27c
1 /*
2 * hdate_hdate.c: convert georgean and hebrew calendars.
4 * Author:
5 * Yaacov Zamir <kzamir@walla.co.il>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
21 #include <gnumeric-config.h>
22 #include <gnumeric.h>
24 #include "hdate.h"
26 /* constants, in 1/18th of minute */
27 #define HOUR 1080
28 #define DAY (24*HOUR)
29 #define WEEK (7*DAY)
30 #define M(h,p) ((h)*HOUR+p)
31 #define MONTH (DAY+M(12,793))
33 /**
34 @brief Return the days from the start
36 @param y The years
37 @warning internal function.
39 int
40 hdate_days_from_start (int y)
42 int m, nm, dw, s, l;
44 l = y * 7 + 1; /* no. of leap months */
45 m = y * 12 + l / 19; /* total no. of months */
46 l %= 19;
47 nm = m * MONTH + M (1 + 6, 779); /* molad new year 3744 (16BC) + 6 hours */
48 s = m * 28 + nm / DAY - 2;
50 nm %= WEEK;
51 dw = nm / DAY;
52 nm %= DAY;
54 /* special cases of Molad Zaken */
55 if ((l < 12 && dw == 3 && nm >= M (9 + 6, 204)) ||
56 (l < 7 && dw == 2 && nm >= M (15 + 6, 589)))
57 s++, dw++;
58 /* ADU */
59 if (dw == 1 || dw == 4 || dw == 6)
60 s++;
61 return s;
64 /**
65 @brief compute hebrew date from gregorian date
67 @param d Day of month 1..31
68 @param m Month 1..12 , if m or d is 0 return current date.
69 @param y Year in 4 digits e.g. 2001
71 int
72 hdate_gdate_to_hdate (int d, int m, int y, int *hd, int *hm, int *hy)
74 int jd;
76 /* sanity checks */
77 if (!(m >= 1 && m <= 12) ||
78 !((d >= 1)
79 && ((y >= 3000 && m == 6 && d <= 59)
80 || (d <= 31))) || !(y > 0))
81 return 1;
83 /* end of cheking */
85 jd = hdate_gdate_to_jd (d, m, y);
87 hdate_jd_to_hdate (jd, hd, hm, hy);
89 return 0;
93 /**
94 @brief compute general date structure from hebrew date
96 @param d Day of month 1..31
97 @param m Month 0..13 , if m or d is 0 return current date.
98 @param y Year in 4 digits e.g. 5731
100 @attention no sanity cheak !!
103 hdate_hdate_to_gdate (int d, int m, int y, int *gd, int *gm, int *gy)
105 int jd;
107 /* sanity checks */
108 if (!(m >= 1 && m <= 12) ||
109 !((d >= 1)
110 && ((y >= 3000 && m == 6 && d <= 59)
111 || (d <= 31))) || !(y > 0))
112 return 1;
114 /* end of cheking */
116 jd = hdate_hdate_to_jd (d, m, y);
118 hdate_jd_to_gdate (jd, gd, gm, gy);
120 return 0;
124 @brief Compute Julian day (jd from Gregorian day, month and year (d, m, y)
125 Algorithm from 'Julian and Gregorian Day Numbers' by Peter Meyer
126 @author Yaacov Zamir ( algorithm from Henry F. Fliegel and Thomas C. Van Flandern ,1968)
128 @param d Day of month 1..31
129 @param m Month 1..12
130 @param y Year in 4 digits e.g. 2001
133 hdate_gdate_to_jd (int d, int m, int y)
135 int jd;
137 jd = (1461 * (y + 4800 + (m - 14) / 12)) / 4 +
138 (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 -
139 (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075;
141 return jd;
145 @brief Converting from the Julian day to the Gregorian day
146 Algorithm from 'Julian and Gregorian Day Numbers' by Peter Meyer
147 @author Yaacov Zamir ( Algorithm, Henry F. Fliegel and Thomas C. Van Flandern ,1968)
149 @param jd Julian day
150 @param d Return Day of month 1..31
151 @param m Return Month 1..12
152 @param y Return Year in 4 digits e.g. 2001
154 void
155 hdate_jd_to_gdate (int jd, int *d, int *m, int *y)
157 int l, n, i, j;
159 l = jd + 68569;
160 n = (4 * l) / 146097;
161 l = l - (146097 * n + 3) / 4;
162 i = (4000 * (l + 1)) / 1461001; /* that's 1,461,001 */
163 l = l - (1461 * i) / 4 + 31;
164 j = (80 * l) / 2447;
165 *d = l - (2447 * j) / 80;
166 l = j / 11;
167 *m = j + 2 - (12 * l);
168 *y = 100 * (n - 49) + i + l; /* that's a lower-case L */
172 @brief Converting from the Julian day to the Hebrew day
173 @author Amos Shapir 1984 (rev. 1985, 1992) Yaacov Zamir 2003-2005
175 @param jd Julian day
176 @param d Return Day of month 1..31
177 @param m Return Month 1..14
178 @param y Return Year in 4 digits e.g. 2001
180 void
181 hdate_jd_to_hdate (int jd, int *d, int *m, int *y)
183 int s;
184 int l, n, i, j;
186 l = jd + 68569;
187 n = (4 * l) / 146097;
188 l = l - (146097 * n + 3) / 4;
189 i = (4000 * (l + 1)) / 1461001; /* that's 1,461,001 */
190 l = l - (1461 * i) / 4 + 31;
191 j = (80 * l) / 2447;
192 l = j / 11;
193 *y = 100 * (n - 49) + i + l; /* that's a lower-case L */
195 *d = jd - 1715119; /* julean to days since 1 Tishrei 3744 */
197 *y += 16;
198 s = hdate_days_from_start (*y);
199 *m = hdate_days_from_start (*y + 1);
201 while (*d >= *m)
202 { /* computed year was underestimated */
203 s = *m;
204 (*y)++;
205 *m = hdate_days_from_start (*y + 1);
207 *d -= s;
208 s = *m - s; /* size of current year */
209 *y += 3744;
211 /* compute day and month */
212 if (*d >= s - 236)
213 { /* last 8 months are regular */
214 *d -= s - 236;
215 *m = *d * 2 / 59;
216 *d -= (*m * 59 + 1) / 2;
217 *m += 4;
218 if (s > 365 && *m <= 5) /* Adar of Meuberet */
219 *m += 8;
221 else
223 /* first 4 months have 117-119 days */
224 s = 114 + s % 10;
225 *m = *d * 4 / s;
226 *d -= (*m * s + 3) / 4;
231 @brief Compute Julian day (jd from Hebrew day, month and year (d, m, y)
232 @author Amos Shapir 1984 (rev. 1985, 1992) Yaacov Zamir 2003-2005
234 @param d Day of month 1..31
235 @param m Month 1..14
236 @param y Year in 4 digits e.g. 5753
239 hdate_hdate_to_jd (int d, int m, int y)
241 int s;
243 y -= 3744;
244 s = hdate_days_from_start (y);
245 d += s;
246 s = hdate_days_from_start (y + 1) - s; /* length of year */
248 if (m == 13)
250 m = 6;
252 if (m == 14)
254 m = 6;
255 d += 30;
258 d += (59 * (m - 1) + 1) / 2; /* regular months */
259 /* special cases */
260 if (s % 10 > 4 && m > 2) /* long Heshvan */
261 d++;
262 if (s % 10 < 4 && m > 3) /* short Kislev */
263 d--;
265 if (s > 365 && m > 6) /* leap year */
266 d += 30;
267 d -= 6002;
269 y = (d + 36525) * 4 / 146097 - 1;
270 d -= y / 4 * 146097 + (y % 4) * 36524;
272 d += 1715119; /* days since 1 Tishrei 3744 to julean */
274 return d;