1 #ifndef MODULE_DATE_CALC
2 #define MODULE_DATE_CALC
3 /*****************************************************************************/
4 /* MODULE NAME: DateCalc.c MODULE TYPE: (lib) */
5 /*****************************************************************************/
6 /* Gregorian calendar date calculations in compliance with */
7 /* ISO/R 2015-1971, DIN 1355 and (to some extent) ISO 8601. */
8 /*****************************************************************************/
9 /* MODULE IMPORTS: */
10 /*****************************************************************************/
11 #include <stdio.h> /* MODULE TYPE: (sys) */
12 #include <stdlib.h> /* MODULE TYPE: (sys) */
13 #include <string.h> /* MODULE TYPE: (sys) */
14 #include <time.h> /* MODULE TYPE: (sys) */
15 #include "ToolBox.h" /* MODULE TYPE: (dat) */
16 /*****************************************************************************/
17 /* MODULE INTERFACE: */
18 /*****************************************************************************/
19
20 /* Make the VMS linker happy: */
21
22 #ifdef VMS
23 #define DateCalc_Day_of_Week_Abbreviation_ DateCalc_DoW_Abbrev_
24 #define DateCalc_nth_weekday_of_month_year DateCalc_nth_weekday
25 #endif
26
27 boolean
28 DateCalc_leap_year (Z_int year);
29
30 boolean
31 DateCalc_check_date (Z_int year,
32 Z_int month,
33 Z_int day);
34
35 boolean
36 DateCalc_check_time (Z_int hour,
37 Z_int min,
38 Z_int sec);
39
40 boolean
41 DateCalc_check_business_date (Z_int year,
42 Z_int week,
43 Z_int dow);
44
45 Z_int
46 DateCalc_Day_of_Year (Z_int year,
47 Z_int month,
48 Z_int day);
49
50 Z_long
51 DateCalc_Date_to_Days (Z_int year,
52 Z_int month,
53 Z_int day);
54
55 Z_int
56 DateCalc_Day_of_Week (Z_int year,
57 Z_int month,
58 Z_int day);
59
60 Z_int
61 DateCalc_Weeks_in_Year (Z_int year);
62
63 Z_int
64 DateCalc_Week_Number (Z_int year,
65 Z_int month,
66 Z_int day);
67
68 boolean
69 DateCalc_week_of_year (Z_int *week, /* O */
70 Z_int *year, /* I/O */
71 Z_int month, /* I */
72 Z_int day); /* I */
73
74 boolean
75 DateCalc_monday_of_week (Z_int week, /* I */
76 Z_int *year, /* I/O */
77 Z_int *month, /* O */
78 Z_int *day); /* O */
79
80 boolean
81 DateCalc_nth_weekday_of_month_year (Z_int *year, /* I/O */
82 Z_int *month, /* I/O */
83 Z_int *day, /* O */
84 Z_int dow, /* I */
85 Z_int n); /* I */
86
87 boolean
88 DateCalc_standard_to_business (Z_int *year, /* I/O */
89 Z_int *week, /* O */
90 Z_int *dow, /* O */
91 Z_int month, /* I */
92 Z_int day); /* I */
93
94 boolean
95 DateCalc_business_to_standard (Z_int *year, /* I/O */
96 Z_int *month, /* O */
97 Z_int *day, /* O */
98 Z_int week, /* I */
99 Z_int dow); /* I */
100
101 Z_long
102 DateCalc_Delta_Days (Z_int year1,
103 Z_int month1,
104 Z_int day1,
105 Z_int year2,
106 Z_int month2,
107 Z_int day2);
108
109 boolean /* PRIVATE */
110 DateCalc_delta_hms (Z_long *Dd, /* I/O */
111 Z_int *Dh, /* O */
112 Z_int *Dm, /* O */
113 Z_int *Ds, /* O */
114 Z_int hour1, /* I */
115 Z_int min1, /* I */
116 Z_int sec1, /* I */
117 Z_int hour2, /* I */
118 Z_int min2, /* I */
119 Z_int sec2); /* I */
120
121 boolean
122 DateCalc_delta_dhms (Z_long *Dd, /* O */
123 Z_int *Dh, /* O */
124 Z_int *Dm, /* O */
125 Z_int *Ds, /* O */
126 Z_int year1, /* I */
127 Z_int month1, /* I */
128 Z_int day1, /* I */
129 Z_int hour1, /* I */
130 Z_int min1, /* I */
131 Z_int sec1, /* I */
132 Z_int year2, /* I */
133 Z_int month2, /* I */
134 Z_int day2, /* I */
135 Z_int hour2, /* I */
136 Z_int min2, /* I */
137 Z_int sec2); /* I */
138
139 boolean
140 DateCalc_delta_ymd (Z_int *year1, /* I/O */
141 Z_int *month1, /* I/O */
142 Z_int *day1, /* I/O */
143 Z_int year2, /* I */
144 Z_int month2, /* I */
145 Z_int day2); /* I */
146
147 boolean
148 DateCalc_delta_ymdhms (Z_int *D_y, /* O */
149 Z_int *D_m, /* O */
150 Z_int *D_d, /* O */
151 Z_int *Dh, /* O */
152 Z_int *Dm, /* O */
153 Z_int *Ds, /* O */
154 Z_int year1, /* I */
155 Z_int month1, /* I */
156 Z_int day1, /* I */
157 Z_int hour1, /* I */
158 Z_int min1, /* I */
159 Z_int sec1, /* I */
160 Z_int year2, /* I */
161 Z_int month2, /* I */
162 Z_int day2, /* I */
163 Z_int hour2, /* I */
164 Z_int min2, /* I */
165 Z_int sec2); /* I */
166
167 boolean
168 DateCalc_norm_delta_ymd (Z_int *year1, /* I/O */
169 Z_int *month1, /* I/O */
170 Z_int *day1, /* I/O */
171 Z_int year2, /* I */
172 Z_int month2, /* I */
173 Z_int day2); /* I */
174
175 boolean
176 DateCalc_norm_delta_ymdhms (Z_int *D_y, /* O */
177 Z_int *D_m, /* O */
178 Z_int *D_d, /* O */
179 Z_int *Dhh, /* O */
180 Z_int *Dmm, /* O */
181 Z_int *Dss, /* O */
182 Z_int year1, /* I */
183 Z_int month1, /* I */
184 Z_int day1, /* I */
185 Z_int hour1, /* I */
186 Z_int min1, /* I */
187 Z_int sec1, /* I */
188 Z_int year2, /* I */
189 Z_int month2, /* I */
190 Z_int day2, /* I */
191 Z_int hour2, /* I */
192 Z_int min2, /* I */
193 Z_int sec2); /* I */
194
195 void
196 DateCalc_Normalize_DHMS (Z_long *Dd, /* I/O */
197 Z_long *Dh, /* I/O */
198 Z_long *Dm, /* I/O */
199 Z_long *Ds); /* I/O */
200
201 boolean
202 DateCalc_add_delta_days (Z_int *year, /* I/O */
203 Z_int *month, /* I/O */
204 Z_int *day, /* I/O */
205 Z_long Dd); /* I */
206
207 boolean
208 DateCalc_add_delta_dhms (Z_int *year, /* I/O */
209 Z_int *month, /* I/O */
210 Z_int *day, /* I/O */
211 Z_int *hour, /* I/O */
212 Z_int *min, /* I/O */
213 Z_int *sec, /* I/O */
214 Z_long Dd, /* I */
215 Z_long Dh, /* I */
216 Z_long Dm, /* I */
217 Z_long Ds); /* I */
218
219 boolean /* PRIVATE */
220 DateCalc_add_year_month (Z_int *year, /* I/O */
221 Z_int *month, /* I/O */
222 Z_long Dy, /* I */
223 Z_long Dm); /* I */
224
225 boolean
226 DateCalc_add_delta_ym (Z_int *year, /* I/O */
227 Z_int *month, /* I/O */
228 Z_int *day, /* I/O */
229 Z_long Dy, /* I */
230 Z_long Dm); /* I */
231
232 boolean
233 DateCalc_add_delta_ymd (Z_int *year, /* I/O */
234 Z_int *month, /* I/O */
235 Z_int *day, /* I/O */
236 Z_long Dy, /* I */
237 Z_long Dm, /* I */
238 Z_long Dd); /* I */
239
240 boolean
241 DateCalc_add_delta_ymdhms (Z_int *year, /* I/O */
242 Z_int *month, /* I/O */
243 Z_int *day, /* I/O */
244 Z_int *hour, /* I/O */
245 Z_int *min, /* I/O */
246 Z_int *sec, /* I/O */
247 Z_long D_y, /* I */
248 Z_long D_m, /* I */
249 Z_long D_d, /* I */
250 Z_long Dh, /* I */
251 Z_long Dm, /* I */
252 Z_long Ds); /* I */
253
254 boolean
255 DateCalc_add_norm_delta_ymd (Z_int *year, /* I/O */
256 Z_int *month, /* I/O */
257 Z_int *day, /* I/O */
258 Z_long Dy, /* I */
259 Z_long Dm, /* I */
260 Z_long Dd); /* I */
261
262 boolean
263 DateCalc_add_norm_delta_ymdhms (Z_int *year, /* I/O */
264 Z_int *month, /* I/O */
265 Z_int *day, /* I/O */
266 Z_int *hour, /* I/O */
267 Z_int *min, /* I/O */
268 Z_int *sec, /* I/O */
269 Z_long D_y, /* I */
270 Z_long D_m, /* I */
271 Z_long D_d, /* I */
272 Z_long Dh, /* I */
273 Z_long Dm, /* I */
274 Z_long Ds); /* I */
275
276 boolean
277 DateCalc_system_clock (Z_int *year, /* O */
278 Z_int *month, /* O */
279 Z_int *day, /* O */
280 Z_int *hour, /* O */
281 Z_int *min, /* O */
282 Z_int *sec, /* O */
283 Z_int *doy, /* O */
284 Z_int *dow, /* O */
285 Z_int *dst, /* O */
286 boolean gmt); /* I */
287
288 boolean
289 DateCalc_gmtime (Z_int *year, /* O */
290 Z_int *month, /* O */
291 Z_int *day, /* O */
292 Z_int *hour, /* O */
293 Z_int *min, /* O */
294 Z_int *sec, /* O */
295 Z_int *doy, /* O */
296 Z_int *dow, /* O */
297 Z_int *dst, /* O */
298 time_t seconds); /* I */
299
300 boolean
301 DateCalc_localtime (Z_int *year, /* O */
302 Z_int *month, /* O */
303 Z_int *day, /* O */
304 Z_int *hour, /* O */
305 Z_int *min, /* O */
306 Z_int *sec, /* O */
307 Z_int *doy, /* O */
308 Z_int *dow, /* O */
309 Z_int *dst, /* O */
310 time_t seconds); /* I */
311
312 boolean
313 DateCalc_mktime (time_t *seconds, /* O */
314 Z_int year, /* I */
315 Z_int month, /* I */
316 Z_int day, /* I */
317 Z_int hour, /* I */
318 Z_int min, /* I */
319 Z_int sec, /* I */
320 Z_int doy, /* I */
321 Z_int dow, /* I */
322 Z_int dst); /* I */
323
324 boolean
325 DateCalc_timezone (Z_int *year, /* O */
326 Z_int *month, /* O */
327 Z_int *day, /* O */
328 Z_int *hour, /* O */
329 Z_int *min, /* O */
330 Z_int *sec, /* O */
331 Z_int *dst, /* O */
332 time_t when); /* I */
333
334 boolean
335 DateCalc_date2time (time_t *seconds, /* O */
336 Z_int year, /* I */
337 Z_int month, /* I */
338 Z_int day, /* I */
339 Z_int hour, /* I */
340 Z_int min, /* I */
341 Z_int sec); /* I */
342
343 boolean
344 DateCalc_time2date (Z_int *year, /* O */
345 Z_int *month, /* O */
346 Z_int *day, /* O */
347 Z_int *hour, /* O */
348 Z_int *min, /* O */
349 Z_int *sec, /* O */
350 time_t seconds); /* I */
351
352 boolean
353 DateCalc_easter_sunday (Z_int *year, /* I/O */
354 Z_int *month, /* O */
355 Z_int *day); /* O */
356
357 Z_int
358 DateCalc_Decode_Month (charptr buffer,
359 Z_int length,
360 Z_int lang);
361
362 Z_int
363 DateCalc_Decode_Day_of_Week (charptr buffer,
364 Z_int length,
365 Z_int lang);
366
367 Z_int
368 DateCalc_Decode_Language (charptr buffer,
369 Z_int length);
370
371 boolean
372 DateCalc_decode_date_eu (charptr buffer, /* I */
373 Z_int *year, /* O */
374 Z_int *month, /* O */
375 Z_int *day, /* O */
376 Z_int lang); /* I */
377
378 boolean
379 DateCalc_decode_date_us (charptr buffer, /* I */
380 Z_int *year, /* O */
381 Z_int *month, /* O */
382 Z_int *day, /* O */
383 Z_int lang); /* I */
384
385 Z_int
386 DateCalc_Fixed_Window (Z_int year);
387
388 Z_int
389 DateCalc_Moving_Window (Z_int year);
390
391 Z_int
392 DateCalc_Compress (Z_int year,
393 Z_int month,
394 Z_int day);
395
396 boolean
397 DateCalc_uncompress (Z_int date, /* I */
398 Z_int *century, /* O */
399 Z_int *year, /* O */
400 Z_int *month, /* O */
401 Z_int *day); /* O */
402
403 boolean
404 DateCalc_check_compressed (Z_int date);
405
406 charptr
407 DateCalc_Compressed_to_Text (Z_int date,
408 Z_int lang);
409
410 charptr
411 DateCalc_Date_to_Text (Z_int year,
412 Z_int month,
413 Z_int day,
414 Z_int lang);
415
416 charptr
417 DateCalc_Date_to_Text_Long (Z_int year,
418 Z_int month,
419 Z_int day,
420 Z_int lang);
421
422 charptr /* O */
423 DateCalc_English_Ordinal (charptr result, /* O */
424 Z_int number); /* I */
425
426 charptr
427 DateCalc_Calendar (Z_int year,
428 Z_int month,
429 boolean orthodox,
430 Z_int lang);
431
432 void
433 DateCalc_Dispose (charptr string);
434
435 N_char
436 DateCalc_ISO_LC (N_char c);
437
438 N_char
439 DateCalc_ISO_UC (N_char c);
440
441 charptr
442 DateCalc_Version (void);
443
444 /*****************************************************************************/
445 /* MODULE RESOURCES: */
446 /*****************************************************************************/
447
448 #define DateCalc_YEAR_OF_EPOCH 70 /* year of reference (epoch) */
449 #define DateCalc_CENTURY_OF_EPOCH 1900 /* century of reference (epoch) */
450 #define DateCalc_EPOCH (DateCalc_CENTURY_OF_EPOCH + DateCalc_YEAR_OF_EPOCH)
451
452 const Z_int DateCalc_Days_in_Year_[2][14] =
453 {
454 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
455 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
456 };
457
458 const Z_int DateCalc_Days_in_Month_[2][13] =
459 {
460 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
461 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
462 };
463
464 #define DateCalc_LANGUAGES 14
465
466 Z_int DateCalc_Language = 1; /* Default = 1 (English) */
467
468 const N_char DateCalc_Month_to_Text_[DateCalc_LANGUAGES+1][13][32] =
469 {
470 {
471 "???", "???", "???", "???", "???", "???", "???",
472 "???", "???", "???", "???", "???", "???"
473 },
474 {
475 "???", "January", "February", "March", "April", "May", "June",
476 "July", "August", "September", "October", "November", "December"
477 },
478 {
479 "???", "janvier", "f�vrier", "mars", "avril", "mai", "juin",
480 "juillet", "ao�t", "septembre", "octobre", "novembre", "d�cembre"
481 },
482 {
483 "???", "Januar", "Februar", "M�rz", "April", "Mai", "Juni",
484 "Juli", "August", "September", "Oktober", "November", "Dezember"
485 },
486 {
487 "???", "enero", "febrero", "marzo", "abril", "mayo", "junio",
488 "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"
489 },
490 {
491 "???", "janeiro", "fevereiro", "mar�o", "abril", "maio", "junho",
492 "julho", "agosto", "setembro", "outubro", "novembro", "dezembro"
493 },
494 {
495 "???", "januari", "februari", "maart", "april", "mei", "juni",
496 "juli", "augustus", "september", "oktober", "november", "december"
497 },
498 {
499 "???", "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno",
500 "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"
501 },
502 {
503 "???", "januar", "februar", "mars", "april", "mai", "juni",
504 "juli", "august", "september", "oktober", "november", "desember"
505 },
506 {
507 "???", "januari", "februari", "mars", "april", "maj", "juni",
508 "juli", "augusti", "september", "oktober", "november", "december"
509 },
510 {
511 "???", "januar", "februar", "marts", "april", "maj", "juni",
512 "juli", "august", "september", "oktober", "november", "december"
513 },
514 {
515 "???", "tammikuu", "helmikuu", "maaliskuu", "huhtikuu",
516 "toukokuu", "kes�kuu", "hein�kuu", "elokuu",
517 "syyskuu", "lokakuu", "marraskuu", "joulukuu"
518 },
519 {
520 "???", "Janu�r", "Febru�r", "M�rcius", "�prilis", "M�jus", "J�nius",
521 "J�lius", "Augusztus", "Szeptember", "Okt�ber", "November", "December"
522 },
523 {
524 "???", "Styczen", "Luty", "Marzec", "Kwiecien", "Maj", "Czerwiec", /* ISO-Latin-1 approximation */
525 "Lipiec", "Sierpien", "Wrzesien", "Pazdziernik", "Listopad", "Grudzien"
526 },
527 {
528 "???", "Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie",
529 "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"
530 }
531 };
532
533 const N_char DateCalc_Day_of_Week_to_Text_[DateCalc_LANGUAGES+1][8][32] =
534 {
535 {
536 "???", "???", "???", "???",
537 "???", "???", "???", "???"
538 },
539 {
540 "???", "Monday", "Tuesday", "Wednesday",
541 "Thursday", "Friday", "Saturday", "Sunday"
542 },
543 {
544 "???", "Lundi", "Mardi", "Mercredi",
545 "Jeudi", "Vendredi", "Samedi", "Dimanche"
546 },
547 {
548 "???", "Montag", "Dienstag", "Mittwoch",
549 "Donnerstag", "Freitag", "Samstag", "Sonntag"
550 },
551 {
552 "???", "Lunes", "Martes", "Mi�rcoles",
553 "Jueves", "Viernes", "S�bado", "Domingo"
554 },
555 {
556 "???", "Segunda-feira", "Ter�a-feira", "Quarta-feira",
557 "Quinta-feira", "Sexta-feira", "S�bado", "Domingo"
558 },
559 {
560 "???", "Maandag", "Dinsdag", "Woensdag",
561 "Donderdag", "Vrijdag", "Zaterdag", "Zondag"
562 },
563 {
564 "???", "Luned�", "Marted�", "Mercoled�",
565 "Gioved�", "Venerd�", "Sabato", "Domenica"
566 },
567 {
568 "???", "mandag", "tirsdag", "onsdag",
569 "torsdag", "fredag", "l�rdag", "s�ndag"
570 },
571 {
572 "???", "m�ndag", "tisdag", "onsdag",
573 "torsdag", "fredag", "l�rdag", "s�ndag"
574 },
575 {
576 "???", "mandag", "tirsdag", "onsdag",
577 "torsdag", "fredag", "l�rdag", "s�ndag"
578 },
579 {
580 "???", "maanantai", "tiistai", "keskiviikko",
581 "torstai", "perjantai", "lauantai", "sunnuntai"
582 },
583 {
584 "???", "h�tf�", "kedd", "szerda",
585 "cs�t�rt�k", "p�ntek", "szombat", "vas�rnap"
586 },
587 {
588 "???", "poniedzialek", "wtorek", "sroda", /* ISO-Latin-1 approximation */
589 "czwartek", "piatek", "sobota", "niedziela"
590 },
591 {
592 "???", "Luni", "Marti", "Miercuri",
593 "Joi", "Vineri", "Sambata", "Duminica"
594 }
595 };
596
597 const N_char DateCalc_Day_of_Week_Abbreviation_[DateCalc_LANGUAGES+1][8][4] =
598
599 /* Fill the fields below _only_ if special abbreviations are needed! */
600 /* Note that the first field serves as a flag and must be non-empty! */
601 {
602 {
603 "", "", "", "", "", "", "", "" /* 0 */
604 },
605 {
606 "", "", "", "", "", "", "", "" /* 1 */
607 },
608 {
609 "", "", "", "", "", "", "", "" /* 2 */
610 },
611 {
612 "", "", "", "", "", "", "", "" /* 3 */
613 },
614 {
615 "", "", "", "", "", "", "", "" /* 4 */
616 },
617 {
618 "", "", "", "", "", "", "", "" /* 5 */
619 /* "???", "2�", "3�", "4�", "5�", "6�", "S�b", "Dom" /* 5 */
620 },
621 {
622 "", "", "", "", "", "", "", "" /* 6 */
623 },
624 {
625 "", "", "", "", "", "", "", "" /* 7 */
626 },
627 {
628 "", "", "", "", "", "", "", "" /* 8 */
629 },
630 {
631 "", "", "", "", "", "", "", "" /* 9 */
632 },
633 {
634 "", "", "", "", "", "", "", "" /* 10 */
635 },
636 {
637 "", "", "", "", "", "", "", "" /* 11 */
638 },
639 {
640 "", "", "", "", "", "", "", "" /* 12 */
641 },
642 {
643 "???", "Pn", "Wt", "Sr", "Cz", "Pt", "So", "Ni" /* 13 */ /* ISO-Latin-1 approximation */
644 },
645 {
646 "", "", "", "", "", "", "", "" /* 14 */
647 }
648 };
649
650 const N_char DateCalc_English_Ordinals_[4][4] =
651 {
652 "th",
653 "st",
654 "nd",
655 "rd"
656 };
657
658 const N_char DateCalc_Date_Long_Format_[DateCalc_LANGUAGES+1][64] =
659 {
660 "%s, %d %s %d", /* 0 Default */
661 "%s, %s %s %d", /* 1 English */
662 "%s %d %s %d", /* 2 Fran�ais */
663 "%s, den %d. %s %d", /* 3 Deutsch */
664 "%s, %d de %s de %d", /* 4 Espa�ol */
665 "%s, dia %d de %s de %d", /* 5 Portugu�s */
666 "%s, %d %s %d", /* 6 Nederlands */
667 "%s, %d %s %d", /* 7 Italiano */
668 "%s, %d. %s %d", /* 8 Norsk */
669 "%s, %d %s %d", /* 9 Svenska */
670 "%s, %d. %s %d", /* 10 Dansk */
671 "%s, %d. %sta %d", /* 11 suomi */
672 "%d. %s %d., %s", /* 12 Magyar */
673 "%s, %d %s %d", /* 13 polski */
674 "%s %d %s %d" /* 14 Romaneste */
675 };
676
677 const N_char DateCalc_Language_to_Text_[DateCalc_LANGUAGES+1][32] =
678 {
679 "???", "English", "Fran�ais", "Deutsch", "Espa�ol",
680 "Portugu�s", "Nederlands", "Italiano", "Norsk", "Svenska",
681 "Dansk", "suomi", "Magyar", "polski", "Romaneste"
682 };
683
684 /*****************************************************************************/
685 /* MODULE IMPLEMENTATION: */
686 /*****************************************************************************/
687
DateCalc_is_digit(N_char c)688 static boolean DateCalc_is_digit(N_char c)
689 {
690 N_int i = (N_int) c;
691
692 if ((i >= 0x30) and (i <= 0x39)) return(true);
693 return(false);
694 }
695
DateCalc_is_alnum(N_char c)696 static boolean DateCalc_is_alnum(N_char c)
697 {
698 N_int i = (N_int) c;
699
700 if (((i >= 0x30) and (i <= 0x39)) or
701 ((i >= 0x41) and (i <= 0x5A)) or
702 ((i >= 0x61) and (i <= 0x7A)) or
703 ((i >= 0xC0) and (i <= 0xD6)) or
704 ((i >= 0xD8) and (i <= 0xF6)) or
705 ((i >= 0xF8) and (i <= 0xFF)))
706 return(true);
707 return(false);
708 }
709
DateCalc_ISO_LC(N_char c)710 N_char DateCalc_ISO_LC(N_char c)
711 {
712 N_int i = (N_int) c;
713
714 if (((i >= 0x41) and (i <= 0x5A)) or
715 ((i >= 0xC0) and (i <= 0xD6)) or
716 ((i >= 0xD8) and (c <= 0xDE))) i += 0x20;
717 return((N_char) i);
718 }
719
DateCalc_ISO_UC(N_char c)720 N_char DateCalc_ISO_UC(N_char c)
721 {
722 N_int i = (N_int) c;
723
724 if (((i >= 0x61) and (i <= 0x7A)) or
725 ((i >= 0xE0) and (i <= 0xF6)) or
726 ((i >= 0xF8) and (c <= 0xFE))) i -= 0x20;
727 return((N_char) i);
728 }
729
DateCalc_Year_to_Days(Z_int year)730 static Z_long DateCalc_Year_to_Days(Z_int year)
731 {
732 Z_long days;
733
734 days = year * 365L;
735 days += year >>= 2;
736 days -= year /= 25;
737 days += year >> 2;
738 return(days);
739 }
740
DateCalc_scan9(charptr str,Z_int len,Z_int idx,boolean neg)741 static boolean DateCalc_scan9(charptr str, Z_int len, Z_int idx, boolean neg)
742 { /* Mnemonic: COBOL "PIC 9" */
743 if ((str != NULL) and (idx >= 0) and (idx < len))
744 return( DateCalc_is_digit(str[idx]) XOR neg );
745 return(false);
746 }
747
DateCalc_scanx(charptr str,Z_int len,Z_int idx,boolean neg)748 static boolean DateCalc_scanx(charptr str, Z_int len, Z_int idx, boolean neg)
749 { /* Mnemonic: COBOL "PIC X" */
750 if ((str != NULL) and (idx >= 0) and (idx < len))
751 return( DateCalc_is_alnum(str[idx]) XOR neg );
752 return(false);
753 }
754
DateCalc_Str2Int(charptr string,Z_int length)755 static Z_int DateCalc_Str2Int(charptr string, Z_int length)
756 {
757 Z_int number = 0;
758
759 while (length-- > 0)
760 {
761 if (number) number *= 10;
762 number += (Z_int) (*string++ - '0');
763 }
764 return(number);
765 }
766
DateCalc_Center(charptr * target,charptr source,Z_int width)767 static void DateCalc_Center(charptr *target, charptr source, Z_int width)
768 {
769 Z_int length;
770 Z_int blank;
771
772 length = strlen((char *)source);
773 if (length > width) length = width;
774 blank = width - length;
775 blank >>= 1;
776 while (blank-- > 0) *(*target)++ = ' ';
777 while (length-- > 0) *(*target)++ = *source++;
778 *(*target)++ = '\n';
779 *(*target) = '\0';
780 }
781
DateCalc_Blank(charptr * target,Z_int count)782 static void DateCalc_Blank(charptr *target, Z_int count)
783 {
784 while (count-- > 0) *(*target)++ = ' ';
785 *(*target) = '\0';
786 }
787
DateCalc_Newline(charptr * target,Z_int count)788 static void DateCalc_Newline(charptr *target, Z_int count)
789 {
790 while (count-- > 0) *(*target)++ = '\n';
791 *(*target) = '\0';
792 }
793
DateCalc_Normalize_Time(Z_long * Dd,Z_long * Dh,Z_long * Dm,Z_long * Ds)794 static void DateCalc_Normalize_Time(Z_long *Dd, Z_long *Dh, Z_long *Dm, Z_long *Ds)
795 {
796 Z_long quot;
797
798 quot = (Z_long) (*Ds / 60L);
799 *Ds -= quot * 60L;
800 *Dm += quot;
801 quot = (Z_long) (*Dm / 60L);
802 *Dm -= quot * 60L;
803 *Dh += quot;
804 quot = (Z_long) (*Dh / 24L);
805 *Dh -= quot * 24L;
806 *Dd += quot;
807 }
808
DateCalc_Normalize_Ranges(Z_long * Dd,Z_long * Dh,Z_long * Dm,Z_long * Ds)809 static void DateCalc_Normalize_Ranges(Z_long *Dd, Z_long *Dh, Z_long *Dm, Z_long *Ds)
810 {
811 Z_long quot;
812
813 /* Prevent overflow errors on systems */
814 /* with short "long"s (e.g. 32 bits): */
815
816 quot = (Z_long) (*Dh / 24L);
817 *Dh -= quot * 24L;
818 *Dd += quot;
819 quot = (Z_long) (*Dm / 60L);
820 *Dm -= quot * 60L;
821 *Dh += quot;
822 DateCalc_Normalize_Time(Dd,Dh,Dm,Ds);
823 }
824
DateCalc_Normalize_Signs(Z_long * Dd,Z_long * Dh,Z_long * Dm,Z_long * Ds)825 static void DateCalc_Normalize_Signs(Z_long *Dd, Z_long *Dh, Z_long *Dm, Z_long *Ds)
826 {
827 Z_long quot;
828
829 quot = (Z_long) (*Ds / 86400L);
830 *Ds -= quot * 86400L;
831 *Dd += quot;
832 if (*Dd != 0L)
833 {
834 if (*Dd > 0L)
835 {
836 if (*Ds < 0L)
837 {
838 *Ds += 86400L;
839 (*Dd)--;
840 }
841 }
842 else
843 {
844 if (*Ds > 0L)
845 {
846 *Ds -= 86400L;
847 (*Dd)++;
848 }
849 }
850 }
851 *Dh = 0L;
852 *Dm = 0L;
853 if (*Ds != 0L) DateCalc_Normalize_Time(Dd,Dh,Dm,Ds);
854 }
855
DateCalc_Normalize_DHMS(Z_long * Dd,Z_long * Dh,Z_long * Dm,Z_long * Ds)856 void DateCalc_Normalize_DHMS(Z_long *Dd, Z_long *Dh, Z_long *Dm, Z_long *Ds)
857 {
858 DateCalc_Normalize_Ranges(Dd,Dh,Dm,Ds);
859 *Ds += ((*Dh * 60L) + *Dm) * 60L;
860 DateCalc_Normalize_Signs(Dd,Dh,Dm,Ds);
861 }
862
863 /*****************************************************************************/
864
DateCalc_leap_year(Z_int year)865 boolean DateCalc_leap_year(Z_int year)
866 {
867 Z_int yy;
868
869 return( ((year AND 0x03) == 0) and
870 ( (((yy = (Z_int) (year / 100)) * 100) != year) or
871 ((yy AND 0x03) == 0) ) );
872 }
873
DateCalc_check_date(Z_int year,Z_int month,Z_int day)874 boolean DateCalc_check_date(Z_int year, Z_int month, Z_int day)
875 {
876 if ((year >= 1) and
877 (month >= 1) and (month <= 12) and
878 (day >= 1) and
879 (day <= DateCalc_Days_in_Month_[DateCalc_leap_year(year)][month]))
880 return(true);
881 return(false);
882 }
883
DateCalc_check_time(Z_int hour,Z_int min,Z_int sec)884 boolean DateCalc_check_time(Z_int hour, Z_int min, Z_int sec)
885 {
886 if ((hour >= 0) and (min >= 0) and (sec >= 0) and
887 (hour < 24) and (min < 60) and (sec < 60))
888 return(true);
889 return(false);
890 }
891
DateCalc_check_business_date(Z_int year,Z_int week,Z_int dow)892 boolean DateCalc_check_business_date(Z_int year, Z_int week, Z_int dow)
893 {
894 if ((year >= 1) and
895 (week >= 1) and (week <= DateCalc_Weeks_in_Year(year)) and
896 (dow >= 1) and (dow <= 7))
897 return(true);
898 return(false);
899 }
900
DateCalc_Day_of_Year(Z_int year,Z_int month,Z_int day)901 Z_int DateCalc_Day_of_Year(Z_int year, Z_int month, Z_int day)
902 {
903 boolean leap;
904
905 if ((year >= 1) and
906 (month >= 1) and (month <= 12) and
907 (day >= 1) and
908 (day <= DateCalc_Days_in_Month_[leap=DateCalc_leap_year(year)][month]))
909 return( DateCalc_Days_in_Year_[leap][month] + day );
910 return(0);
911 }
912
DateCalc_Date_to_Days(Z_int year,Z_int month,Z_int day)913 Z_long DateCalc_Date_to_Days(Z_int year, Z_int month, Z_int day)
914 {
915 boolean leap;
916
917 if ((year >= 1) and
918 (month >= 1) and (month <= 12) and
919 (day >= 1) and
920 (day <= DateCalc_Days_in_Month_[leap=DateCalc_leap_year(year)][month]))
921 return( DateCalc_Year_to_Days(--year) +
922 DateCalc_Days_in_Year_[leap][month] + day );
923 return(0L);
924 }
925
DateCalc_Day_of_Week(Z_int year,Z_int month,Z_int day)926 Z_int DateCalc_Day_of_Week(Z_int year, Z_int month, Z_int day)
927 {
928 Z_long days;
929
930 days = DateCalc_Date_to_Days(year,month,day);
931 if (days > 0L)
932 {
933 days--;
934 days %= 7L;
935 days++;
936 }
937 return( (Z_int) days );
938 }
939
DateCalc_Weeks_in_Year(Z_int year)940 Z_int DateCalc_Weeks_in_Year(Z_int year)
941 {
942 return( 52 + ((DateCalc_Day_of_Week(year,1,1) == 4) or
943 (DateCalc_Day_of_Week(year,12,31) == 4)) );
944 }
945
DateCalc_Week_Number(Z_int year,Z_int month,Z_int day)946 Z_int DateCalc_Week_Number(Z_int year, Z_int month, Z_int day)
947 {
948 Z_int first;
949
950 first = DateCalc_Day_of_Week(year,1,1) - 1;
951 return( (Z_int)
952 ( (DateCalc_Delta_Days(year,1,1, year,month,day) + first) / 7L )
953 + (first < 4) );
954 }
955
DateCalc_week_of_year(Z_int * week,Z_int * year,Z_int month,Z_int day)956 boolean DateCalc_week_of_year(Z_int *week,
957 Z_int *year, Z_int month, Z_int day)
958 {
959 if (DateCalc_check_date(*year,month,day))
960 {
961 *week = DateCalc_Week_Number(*year,month,day);
962 if (*week == 0) *week = DateCalc_Weeks_in_Year(--(*year));
963 else if (*week > DateCalc_Weeks_in_Year(*year))
964 {
965 *week = 1;
966 (*year)++;
967 }
968 return(true);
969 }
970 return(false);
971 }
972
DateCalc_monday_of_week(Z_int week,Z_int * year,Z_int * month,Z_int * day)973 boolean DateCalc_monday_of_week(Z_int week,
974 Z_int *year, Z_int *month, Z_int *day)
975 {
976 Z_int first;
977
978 *month = *day = 1;
979 first = DateCalc_Day_of_Week(*year,1,1) - 1;
980 if (first < 4) week--;
981 return( DateCalc_add_delta_days(year,month,day, (week * 7L - first)) );
982 }
983
984 boolean
DateCalc_nth_weekday_of_month_year(Z_int * year,Z_int * month,Z_int * day,Z_int dow,Z_int n)985 DateCalc_nth_weekday_of_month_year(Z_int *year, Z_int *month, Z_int *day,
986 Z_int dow, Z_int n)
987 {
988 Z_int mm = *month;
989 Z_int first;
990 Z_long delta;
991
992 *day = 1;
993 if ((*year < 1) or
994 (mm < 1) or (mm > 12) or
995 (dow < 1) or (dow > 7) or
996 (n < 1) or (n > 5))
997 return(false);
998 first = DateCalc_Day_of_Week(*year,mm,1);
999 if (dow < first) dow += 7;
1000 delta = (Z_long) (dow - first);
1001 delta += (n-1) * 7L;
1002 if (DateCalc_add_delta_days(year,month,day,delta) and (*month == mm))
1003 return(true);
1004 return(false);
1005 }
1006
DateCalc_standard_to_business(Z_int * year,Z_int * week,Z_int * dow,Z_int month,Z_int day)1007 boolean DateCalc_standard_to_business(Z_int *year, Z_int *week, Z_int *dow,
1008 Z_int month, Z_int day)
1009 {
1010 Z_int yy = *year;
1011
1012 if (DateCalc_week_of_year(week,year,month,day))
1013 {
1014 *dow = DateCalc_Day_of_Week(yy,month,day);
1015 return(true);
1016 }
1017 return(false);
1018 }
1019
DateCalc_business_to_standard(Z_int * year,Z_int * month,Z_int * day,Z_int week,Z_int dow)1020 boolean DateCalc_business_to_standard(Z_int *year, Z_int *month, Z_int *day,
1021 Z_int week, Z_int dow)
1022 {
1023 Z_int first;
1024 Z_long delta;
1025
1026 if (DateCalc_check_business_date(*year,week,dow))
1027 {
1028 *month = *day = 1;
1029 first = DateCalc_Day_of_Week(*year,1,1);
1030 delta = ((week + (first > 4) - 1) * 7L) + (dow - first);
1031 return( DateCalc_add_delta_days(year,month,day,delta) );
1032 }
1033 return(false);
1034 }
1035
DateCalc_Delta_Days(Z_int year1,Z_int month1,Z_int day1,Z_int year2,Z_int month2,Z_int day2)1036 Z_long DateCalc_Delta_Days(Z_int year1, Z_int month1, Z_int day1,
1037 Z_int year2, Z_int month2, Z_int day2)
1038 {
1039 return( DateCalc_Date_to_Days(year2,month2,day2) -
1040 DateCalc_Date_to_Days(year1,month1,day1) );
1041 }
1042
DateCalc_delta_hms(Z_long * Dd,Z_int * Dh,Z_int * Dm,Z_int * Ds,Z_int hour1,Z_int min1,Z_int sec1,Z_int hour2,Z_int min2,Z_int sec2)1043 boolean DateCalc_delta_hms(Z_long *Dd,
1044 Z_int *Dh, Z_int *Dm, Z_int *Ds,
1045 Z_int hour1, Z_int min1, Z_int sec1,
1046 Z_int hour2, Z_int min2, Z_int sec2)
1047 {
1048 Z_long HH;
1049 Z_long MM;
1050 Z_long SS;
1051
1052 if (DateCalc_check_time(hour1,min1,sec1) and
1053 DateCalc_check_time(hour2,min2,sec2))
1054 {
1055 SS = ((((hour2 * 60L) + min2) * 60L) + sec2) -
1056 ((((hour1 * 60L) + min1) * 60L) + sec1);
1057 DateCalc_Normalize_Signs(Dd,&HH,&MM,&SS);
1058 *Dh = (Z_int) HH;
1059 *Dm = (Z_int) MM;
1060 *Ds = (Z_int) SS;
1061 return(true);
1062 }
1063 return(false);
1064 }
1065
DateCalc_delta_dhms(Z_long * Dd,Z_int * Dh,Z_int * Dm,Z_int * Ds,Z_int year1,Z_int month1,Z_int day1,Z_int hour1,Z_int min1,Z_int sec1,Z_int year2,Z_int month2,Z_int day2,Z_int hour2,Z_int min2,Z_int sec2)1066 boolean DateCalc_delta_dhms(Z_long *Dd,
1067 Z_int *Dh, Z_int *Dm, Z_int *Ds,
1068 Z_int year1, Z_int month1, Z_int day1,
1069 Z_int hour1, Z_int min1, Z_int sec1,
1070 Z_int year2, Z_int month2, Z_int day2,
1071 Z_int hour2, Z_int min2, Z_int sec2)
1072 {
1073 *Dd = *Dh = *Dm = *Ds = 0;
1074 if (DateCalc_check_date(year1,month1,day1) and
1075 DateCalc_check_date(year2,month2,day2))
1076 {
1077 *Dd = DateCalc_Delta_Days(year1,month1,day1, year2,month2,day2);
1078 return( DateCalc_delta_hms(Dd,Dh,Dm,Ds,
1079 hour1,min1,sec1,
1080 hour2,min2,sec2) );
1081 }
1082 return(false);
1083 }
1084
DateCalc_delta_ymd(Z_int * year1,Z_int * month1,Z_int * day1,Z_int year2,Z_int month2,Z_int day2)1085 boolean DateCalc_delta_ymd(Z_int *year1, Z_int *month1, Z_int *day1,
1086 Z_int year2, Z_int month2, Z_int day2)
1087 {
1088 if (DateCalc_check_date(*year1,*month1,*day1) and
1089 DateCalc_check_date(year2,month2,day2))
1090 {
1091 *day1 = day2 - *day1;
1092 *month1 = month2 - *month1;
1093 *year1 = year2 - *year1;
1094 return(true);
1095 }
1096 return(false);
1097 }
1098
DateCalc_delta_ymdhms(Z_int * D_y,Z_int * D_m,Z_int * D_d,Z_int * Dh,Z_int * Dm,Z_int * Ds,Z_int year1,Z_int month1,Z_int day1,Z_int hour1,Z_int min1,Z_int sec1,Z_int year2,Z_int month2,Z_int day2,Z_int hour2,Z_int min2,Z_int sec2)1099 boolean DateCalc_delta_ymdhms(Z_int *D_y, Z_int *D_m, Z_int *D_d,
1100 Z_int *Dh, Z_int *Dm, Z_int *Ds,
1101 Z_int year1, Z_int month1, Z_int day1,
1102 Z_int hour1, Z_int min1, Z_int sec1,
1103 Z_int year2, Z_int month2, Z_int day2,
1104 Z_int hour2, Z_int min2, Z_int sec2)
1105 {
1106 Z_long Dd;
1107
1108 if (not DateCalc_delta_ymd(&year1,&month1,&day1, year2,month2,day2))
1109 return(false);
1110 Dd = (Z_long) day1;
1111 if (not DateCalc_delta_hms(&Dd,Dh,Dm,Ds, hour1,min1,sec1, hour2,min2,sec2))
1112 return(false);
1113 *D_y = year1;
1114 *D_m = month1;
1115 *D_d = (Z_int) Dd;
1116 return(true);
1117 }
1118
DateCalc_norm_delta_ymd(Z_int * year1,Z_int * month1,Z_int * day1,Z_int year2,Z_int month2,Z_int day2)1119 boolean DateCalc_norm_delta_ymd(Z_int *year1, Z_int *month1, Z_int *day1,
1120 Z_int year2, Z_int month2, Z_int day2)
1121 {
1122 Z_long Dy = 0L;
1123 Z_long Dm = 0L;
1124 Z_long Dd = 0L;
1125 Z_long d2;
1126 Z_int ty;
1127 Z_int tm;
1128 Z_int td;
1129
1130 if (DateCalc_check_date(*year1,*month1,*day1) and
1131 DateCalc_check_date(year2,month2,day2))
1132 {
1133 d2 = DateCalc_Date_to_Days(year2,month2,day2);
1134 Dd = d2-DateCalc_Date_to_Days(*year1,*month1,*day1);
1135 if ((Dd < -30L) or (Dd > 30L))
1136 {
1137 Dy = (Z_long) (year2 - *year1);
1138 Dm = (Z_long) (month2 - *month1);
1139 ty=*year1; tm=*month1; td=*day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td);
1140 if (!(((Dy >= 0L) and (Dm >= 0L) and (Dd >= 0L)) or
1141 ((Dy <= 0L) and (Dm <= 0L) and (Dd <= 0L))))
1142 {
1143 if ((Dy < 0L) and (Dm > 0L)) { Dy++; Dm -= 12L; }
1144 else if ((Dy > 0L) and (Dm < 0L)) { Dy--; Dm += 12L; }
1145 if ((Dm < 0L) and (Dd > 0L)) { Dm++; ty=*year1; tm=*month1; td=*day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1146 else if ((Dm > 0L) and (Dd < 0L)) { Dm--; ty=*year1; tm=*month1; td=*day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1147 if ((Dy < 0L) and (Dd > 0L)) { Dy++; Dm -= 12L; }
1148 else if ((Dy > 0L) and (Dd < 0L)) { Dy--; Dm += 12L; }
1149 if ((Dm < 0L) and (Dd > 0L)) { Dm++; ty=*year1; tm=*month1; td=*day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1150 else if ((Dm > 0L) and (Dd < 0L)) { Dm--; ty=*year1; tm=*month1; td=*day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1151 }
1152 }
1153 *year1 = (Z_int) Dy;
1154 *month1 = (Z_int) Dm;
1155 *day1 = (Z_int) Dd;
1156 return(true);
1157 }
1158 return(false);
1159 }
1160
DateCalc_norm_delta_ymdhms(Z_int * D_y,Z_int * D_m,Z_int * D_d,Z_int * Dhh,Z_int * Dmm,Z_int * Dss,Z_int year1,Z_int month1,Z_int day1,Z_int hour1,Z_int min1,Z_int sec1,Z_int year2,Z_int month2,Z_int day2,Z_int hour2,Z_int min2,Z_int sec2)1161 boolean DateCalc_norm_delta_ymdhms(Z_int *D_y, Z_int *D_m, Z_int *D_d,
1162 Z_int *Dhh, Z_int *Dmm, Z_int *Dss,
1163 Z_int year1, Z_int month1, Z_int day1,
1164 Z_int hour1, Z_int min1, Z_int sec1,
1165 Z_int year2, Z_int month2, Z_int day2,
1166 Z_int hour2, Z_int min2, Z_int sec2)
1167 {
1168 Z_long Dy = 0L;
1169 Z_long Dm = 0L;
1170 Z_long Dd = 0L;
1171 Z_long d2, hh, mm, ss;
1172 Z_int ty;
1173 Z_int tm;
1174 Z_int td;
1175
1176 if (DateCalc_check_date(year1,month1,day1) and
1177 DateCalc_check_time(hour1,min1, sec1) and
1178 DateCalc_check_date(year2,month2,day2) and
1179 DateCalc_check_time(hour1,min2, sec2))
1180 {
1181 ss = ( (hour2-hour1) * 60L + (min2-min1) ) * 60L + (sec2-sec1);
1182 d2 = DateCalc_Date_to_Days(year2,month2,day2);
1183 Dd = d2-DateCalc_Date_to_Days(year1,month1,day1);
1184 if ((Dd < -30L) or (Dd > 30L))
1185 {
1186 Dy = (Z_long) (year2 - year1);
1187 Dm = (Z_long) (month2 - month1);
1188 ty=year1; tm=month1; td=day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td);
1189 if (!(((Dy >= 0L) and (Dm >= 0L) and (Dd >= 0L) and (ss >= 0L)) or
1190 ((Dy <= 0L) and (Dm <= 0L) and (Dd <= 0L) and (ss <= 0L))))
1191 {
1192 if ((Dy < 0L) and (Dm > 0L)) { Dy++; Dm -= 12L; }
1193 else if ((Dy > 0L) and (Dm < 0L)) { Dy--; Dm += 12L; }
1194 if ((Dm < 0L) and (Dd > 0L)) { Dm++; ty=year1; tm=month1; td=day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1195 else if ((Dm > 0L) and (Dd < 0L)) { Dm--; ty=year1; tm=month1; td=day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1196 if ((Dy < 0L) and (Dd > 0L)) { Dy++; Dm -= 12L; }
1197 else if ((Dy > 0L) and (Dd < 0L)) { Dy--; Dm += 12L; }
1198 if ((Dm < 0L) and (Dd > 0L)) { Dm++; ty=year1; tm=month1; td=day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1199 else if ((Dm > 0L) and (Dd < 0L)) { Dm--; ty=year1; tm=month1; td=day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1200 if ((Dd < 0L) and (ss > 0L)) { Dd++; ss -= 86400L; }
1201 else if ((Dd > 0L) and (ss < 0L)) { Dd--; ss += 86400L; }
1202 if ((Dm < 0L) and (ss > 0L)) { Dm++; ty=year1; tm=month1; td=day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1203 else if ((Dm > 0L) and (ss < 0L)) { Dm--; ty=year1; tm=month1; td=day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1204 if ((Dy < 0L) and (ss > 0L)) { Dy++; Dm -= 12L; }
1205 else if ((Dy > 0L) and (ss < 0L)) { Dy--; Dm += 12L; }
1206 if ((Dm < 0L) and (ss > 0L)) { Dm++; ty=year1; tm=month1; td=day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1207 else if ((Dm > 0L) and (ss < 0L)) { Dm--; ty=year1; tm=month1; td=day1; if (!DateCalc_add_delta_ym(&ty,&tm,&td,Dy,Dm)) return(false); Dd=d2-DateCalc_Date_to_Days(ty,tm,td); }
1208 if ((Dd < 0L) and (ss > 0L)) { Dd++; ss -= 86400L; }
1209 else if ((Dd > 0L) and (ss < 0L)) { Dd--; ss += 86400L; }
1210 }
1211 }
1212 else
1213 {
1214 if ((Dd < 0L) and (ss > 0L)) { Dd++; ss -= 86400L; }
1215 else if ((Dd > 0L) and (ss < 0L)) { Dd--; ss += 86400L; }
1216 }
1217 mm = (Z_long) ( ss / 60 );
1218 ss -= mm * 60;
1219 hh = (Z_long) ( mm / 60 );
1220 mm -= hh * 60;
1221 *D_y = (Z_int) Dy;
1222 *D_m = (Z_int) Dm;
1223 *D_d = (Z_int) Dd;
1224 *Dhh = (Z_int) hh;
1225 *Dmm = (Z_int) mm;
1226 *Dss = (Z_int) ss;
1227 return(true);
1228 }
1229 return(false);
1230 }
1231
DateCalc_add_delta_days(Z_int * year,Z_int * month,Z_int * day,Z_long Dd)1232 boolean DateCalc_add_delta_days(Z_int *year, Z_int *month, Z_int *day,
1233 Z_long Dd)
1234 {
1235 Z_long days;
1236 boolean leap;
1237
1238 if (((days = DateCalc_Date_to_Days(*year,*month,*day)) > 0L) and
1239 ((days += Dd) > 0L))
1240 {
1241 if (Dd != 0L)
1242 {
1243 *year = (Z_int) ( days / 365.2425 );
1244 *day = (Z_int) ( days - DateCalc_Year_to_Days(*year) );
1245 if (*day < 1)
1246 {
1247 *day = (Z_int) ( days - DateCalc_Year_to_Days(*year-1) );
1248 }
1249 else (*year)++;
1250 leap = DateCalc_leap_year(*year);
1251 if (*day > DateCalc_Days_in_Year_[leap][13])
1252 {
1253 *day -= DateCalc_Days_in_Year_[leap][13];
1254 leap = DateCalc_leap_year(++(*year));
1255 }
1256 for ( *month = 12; *month >= 1; (*month)-- )
1257 {
1258 if (*day > DateCalc_Days_in_Year_[leap][*month])
1259 {
1260 *day -= DateCalc_Days_in_Year_[leap][*month];
1261 break;
1262 }
1263 }
1264 }
1265 return(true);
1266 }
1267 return(false);
1268 }
1269
DateCalc_add_delta_dhms(Z_int * year,Z_int * month,Z_int * day,Z_int * hour,Z_int * min,Z_int * sec,Z_long Dd,Z_long Dh,Z_long Dm,Z_long Ds)1270 boolean DateCalc_add_delta_dhms(Z_int *year, Z_int *month, Z_int *day,
1271 Z_int *hour, Z_int *min, Z_int *sec,
1272 Z_long Dd,
1273 Z_long Dh, Z_long Dm, Z_long Ds)
1274 {
1275 if (DateCalc_check_date(*year,*month,*day) and
1276 DateCalc_check_time(*hour,*min,*sec))
1277 {
1278 DateCalc_Normalize_Ranges(&Dd,&Dh,&Dm,&Ds);
1279 Ds += ((((*hour * 60L) + *min) * 60L) + *sec) +
1280 ((( Dh * 60L) + Dm) * 60L);
1281 while (Ds < 0L)
1282 {
1283 Ds += 86400L;
1284 Dd--;
1285 }
1286 if (Ds > 0L)
1287 {
1288 Dh = 0L;
1289 Dm = 0L;
1290 DateCalc_Normalize_Time(&Dd,&Dh,&Dm,&Ds);
1291 *hour = (Z_int) Dh;
1292 *min = (Z_int) Dm;
1293 *sec = (Z_int) Ds;
1294 }
1295 else *hour = *min = *sec = 0;
1296 return( DateCalc_add_delta_days(year,month,day,Dd) );
1297 }
1298 return(false);
1299 }
1300
DateCalc_add_year_month(Z_int * year,Z_int * month,Z_long Dy,Z_long Dm)1301 boolean DateCalc_add_year_month(Z_int *year, Z_int *month,
1302 Z_long Dy, Z_long Dm)
1303 {
1304 Z_long quot;
1305
1306 if ((*year < 1) or (*month < 1) or (*month > 12)) return(false);
1307 if (Dm != 0L)
1308 {
1309 Dm += (Z_long) (*month - 1);
1310 quot = (Z_long) (Dm / 12L);
1311 Dm -= quot * 12L;
1312 if (Dm < 0L)
1313 {
1314 Dm += 12L;
1315 quot--;
1316 }
1317 *month = (Z_int) (Dm + 1);
1318 Dy += quot;
1319 }
1320 if (Dy != 0L)
1321 {
1322 Dy += (Z_long) *year;
1323 *year = (Z_int) Dy;
1324 }
1325 if (*year < 1) return(false);
1326 return(true);
1327 }
1328
DateCalc_add_delta_ym(Z_int * year,Z_int * month,Z_int * day,Z_long Dy,Z_long Dm)1329 boolean DateCalc_add_delta_ym(Z_int *year, Z_int *month, Z_int *day,
1330 Z_long Dy, Z_long Dm)
1331 {
1332 Z_int Dd;
1333
1334 if (not DateCalc_check_date(*year,*month,*day)) return(false);
1335 if (not DateCalc_add_year_month(year,month,Dy,Dm)) return(false);
1336 if (*day >
1337 (Dd = DateCalc_Days_in_Month_[DateCalc_leap_year(*year)][*month]))
1338 *day = Dd;
1339 return(true);
1340 }
1341
DateCalc_add_delta_ymd(Z_int * year,Z_int * month,Z_int * day,Z_long Dy,Z_long Dm,Z_long Dd)1342 boolean DateCalc_add_delta_ymd(Z_int *year, Z_int *month, Z_int *day,
1343 Z_long Dy, Z_long Dm, Z_long Dd)
1344 {
1345 if (not DateCalc_check_date(*year,*month,*day)) return(false);
1346 if (not DateCalc_add_year_month(year,month,Dy,Dm)) return(false);
1347 Dd += (Z_long) (*day - 1);
1348 *day = 1;
1349 return( DateCalc_add_delta_days(year,month,day,Dd) );
1350 }
1351
DateCalc_add_delta_ymdhms(Z_int * year,Z_int * month,Z_int * day,Z_int * hour,Z_int * min,Z_int * sec,Z_long D_y,Z_long D_m,Z_long D_d,Z_long Dh,Z_long Dm,Z_long Ds)1352 boolean DateCalc_add_delta_ymdhms(Z_int *year, Z_int *month, Z_int *day,
1353 Z_int *hour, Z_int *min, Z_int *sec,
1354 Z_long D_y, Z_long D_m, Z_long D_d,
1355 Z_long Dh, Z_long Dm, Z_long Ds)
1356 {
1357 if (not (DateCalc_check_date(*year,*month,*day) and
1358 DateCalc_check_time(*hour,*min,*sec))) return(false);
1359 if (not DateCalc_add_year_month(year,month,D_y,D_m)) return(false);
1360 D_d += (Z_long) (*day - 1);
1361 *day = 1;
1362 return( DateCalc_add_delta_dhms(year,month,day,hour,min,sec,D_d,Dh,Dm,Ds) );
1363 }
1364
DateCalc_add_norm_delta_ymd(Z_int * year,Z_int * month,Z_int * day,Z_long Dy,Z_long Dm,Z_long Dd)1365 boolean DateCalc_add_norm_delta_ymd(Z_int *year, Z_int *month, Z_int *day,
1366 Z_long Dy, Z_long Dm, Z_long Dd)
1367 {
1368 if (not DateCalc_add_delta_ym(year,month,day,Dy,Dm)) return(false);
1369 return( DateCalc_add_delta_days(year,month,day,Dd) );
1370 }
1371
DateCalc_add_norm_delta_ymdhms(Z_int * year,Z_int * month,Z_int * day,Z_int * hour,Z_int * min,Z_int * sec,Z_long D_y,Z_long D_m,Z_long D_d,Z_long Dh,Z_long Dm,Z_long Ds)1372 boolean DateCalc_add_norm_delta_ymdhms(Z_int *year, Z_int *month, Z_int *day,
1373 Z_int *hour, Z_int *min, Z_int *sec,
1374 Z_long D_y, Z_long D_m, Z_long D_d,
1375 Z_long Dh, Z_long Dm, Z_long Ds)
1376 {
1377 if (not DateCalc_add_delta_ym(year,month,day,D_y,D_m)) return(false);
1378 return( DateCalc_add_delta_dhms(year,month,day,hour,min,sec,D_d,Dh,Dm,Ds) );
1379 }
1380
DateCalc_system_clock(Z_int * year,Z_int * month,Z_int * day,Z_int * hour,Z_int * min,Z_int * sec,Z_int * doy,Z_int * dow,Z_int * dst,boolean gmt)1381 boolean DateCalc_system_clock(Z_int *year, Z_int *month, Z_int *day,
1382 Z_int *hour, Z_int *min, Z_int *sec,
1383 Z_int *doy, Z_int *dow, Z_int *dst,
1384 boolean gmt)
1385 {
1386 time_t seconds;
1387 struct tm *date;
1388
1389 if (time(&seconds) >= 0)
1390 {
1391 if (gmt) date = gmtime(&seconds);
1392 else date = localtime(&seconds);
1393 if (date != NULL)
1394 {
1395 *year = (*date).tm_year + 1900;
1396 *month = (*date).tm_mon + 1;
1397 *day = (*date).tm_mday;
1398 *hour = (*date).tm_hour;
1399 *min = (*date).tm_min;
1400 *sec = (*date).tm_sec;
1401 *doy = (*date).tm_yday + 1;
1402 *dow = (*date).tm_wday; if (*dow == 0) *dow = 7;
1403 *dst = (*date).tm_isdst;
1404 if (*dst != 0)
1405 {
1406 if (*dst < 0) *dst = -1;
1407 else *dst = 1;
1408 }
1409 return(true);
1410 }
1411 }
1412 return(false);
1413 }
1414
DateCalc_gmtime(Z_int * year,Z_int * month,Z_int * day,Z_int * hour,Z_int * min,Z_int * sec,Z_int * doy,Z_int * dow,Z_int * dst,time_t seconds)1415 boolean DateCalc_gmtime(Z_int *year, Z_int *month, Z_int *day,
1416 Z_int *hour, Z_int *min, Z_int *sec,
1417 Z_int *doy, Z_int *dow, Z_int *dst,
1418 time_t seconds)
1419 {
1420 struct tm *date;
1421
1422 if ((seconds >= 0) and ((date = gmtime(&seconds)) != NULL))
1423 {
1424 *year = (*date).tm_year + 1900;
1425 *month = (*date).tm_mon + 1;
1426 *day = (*date).tm_mday;
1427 *hour = (*date).tm_hour;
1428 *min = (*date).tm_min;
1429 *sec = (*date).tm_sec;
1430 *doy = (*date).tm_yday + 1;
1431 *dow = (*date).tm_wday; if (*dow == 0) *dow = 7;
1432 *dst = (*date).tm_isdst;
1433 if (*dst != 0)
1434 {
1435 if (*dst < 0) *dst = -1;
1436 else *dst = 1;
1437 }
1438 return(true);
1439 }
1440 return(false);
1441 }
1442
DateCalc_localtime(Z_int * year,Z_int * month,Z_int * day,Z_int * hour,Z_int * min,Z_int * sec,Z_int * doy,Z_int * dow,Z_int * dst,time_t seconds)1443 boolean DateCalc_localtime(Z_int *year, Z_int *month, Z_int *day,
1444 Z_int *hour, Z_int *min, Z_int *sec,
1445 Z_int *doy, Z_int *dow, Z_int *dst,
1446 time_t seconds)
1447 {
1448 struct tm *date;
1449
1450 if ((seconds >= 0) and ((date = localtime(&seconds)) != NULL))
1451 {
1452 *year = (*date).tm_year + 1900;
1453 *month = (*date).tm_mon + 1;
1454 *day = (*date).tm_mday;
1455 *hour = (*date).tm_hour;
1456 *min = (*date).tm_min;
1457 *sec = (*date).tm_sec;
1458 *doy = (*date).tm_yday + 1;
1459 *dow = (*date).tm_wday; if (*dow == 0) *dow = 7;
1460 *dst = (*date).tm_isdst;
1461 if (*dst != 0)
1462 {
1463 if (*dst < 0) *dst = -1;
1464 else *dst = 1;
1465 }
1466 return(true);
1467 }
1468 return(false);
1469 }
1470
1471 /* MacOS (Classic): */
1472 /* <695056.0> = Fri 1-Jan-1904 00:00:00 (time=0x00000000) */
1473 /* <744766.23295> = Mon 6-Feb-2040 06:28:15 (time=0xFFFFFFFF) */
1474
1475 /* Unix: */
1476 /* <719163.0> = Thu 1-Jan-1970 00:00:00 (time=0x00000000) */
1477 /* <744018.11647> = Tue 19-Jan-2038 03:14:07 (time=0x7FFFFFFF) */
1478
DateCalc_mktime(time_t * seconds,Z_int year,Z_int month,Z_int day,Z_int hour,Z_int min,Z_int sec,Z_int doy,Z_int dow,Z_int dst)1479 boolean DateCalc_mktime(time_t *seconds,
1480 Z_int year, Z_int month, Z_int day,
1481 Z_int hour, Z_int min, Z_int sec,
1482 Z_int doy, Z_int dow, Z_int dst)
1483 {
1484 struct tm date;
1485
1486 *seconds = (time_t) 0;
1487
1488 #ifdef MACOS_TRADITIONAL
1489 if ( (year < 1904) or (year > 2040) or
1490 #else
1491 if ( (year < 1970) or (year > 2038) or
1492 #endif
1493 (month < 1) or (month > 12) or
1494 (day < 1) or (day > 31) or
1495 (hour < 0) or (hour > 23) or
1496 (min < 0) or (min > 59) or
1497 (sec < 0) or (sec > 59) )
1498 return(false);
1499
1500 #ifdef MACOS_TRADITIONAL
1501 if ( (year == 2040) and ( (month > 2) or
1502 ( (month == 2) and ( (day > 6) or
1503 ( (day == 6) and ( (hour > 6) or
1504 ( (hour == 6) and ( (min > 28) or
1505 ( (min == 28) and (sec > 15) ) ))))))) )
1506 return(false);
1507 #else
1508 if ( (year == 2038) and ( (month > 1) or
1509 ( (month == 1) and ( (day > 19) or
1510 ( (day == 19) and ( (hour > 3) or
1511 ( (hour == 3) and ( (min > 14) or
1512 ( (min == 14) and (sec > 7) ) ))))))) )
1513 return(false);
1514 #endif
1515
1516 year -= 1900;
1517 month--;
1518 if (doy <= 0) doy = -1;
1519 else doy--;
1520 if (dow <= 0) dow = -1; else
1521 if (dow == 7) dow = 0;
1522 if (dst != 0)
1523 {
1524 if (dst < 0) dst = -1;
1525 else dst = 1;
1526 }
1527 date.tm_year = year;
1528 date.tm_mon = month;
1529 date.tm_mday = day;
1530 date.tm_hour = hour;
1531 date.tm_min = min;
1532 date.tm_sec = sec;
1533 date.tm_yday = doy;
1534 date.tm_wday = dow;
1535 date.tm_isdst = dst;
1536 *seconds = mktime(&date);
1537 return(*seconds >= 0);
1538 }
1539
DateCalc_timezone(Z_int * year,Z_int * month,Z_int * day,Z_int * hour,Z_int * min,Z_int * sec,Z_int * dst,time_t when)1540 boolean DateCalc_timezone(Z_int *year, Z_int *month, Z_int *day,
1541 Z_int *hour, Z_int *min, Z_int *sec,
1542 Z_int *dst, time_t when)
1543 {
1544 struct tm *date;
1545 Z_int year1;
1546 Z_int month1;
1547 Z_int day1;
1548 Z_int hour1;
1549 Z_int min1;
1550 Z_int sec1;
1551 Z_int year2;
1552 Z_int month2;
1553 Z_int day2;
1554 Z_int hour2;
1555 Z_int min2;
1556 Z_int sec2;
1557
1558 if (when >= 0)
1559 {
1560 if ((date = gmtime(&when)) == NULL) return(false);
1561 year1 = (*date).tm_year + 1900;
1562 month1 = (*date).tm_mon + 1;
1563 day1 = (*date).tm_mday;
1564 hour1 = (*date).tm_hour;
1565 min1 = (*date).tm_min;
1566 sec1 = (*date).tm_sec;
1567 if ((date = localtime(&when)) == NULL) return(false);
1568 year2 = (*date).tm_year + 1900;
1569 month2 = (*date).tm_mon + 1;
1570 day2 = (*date).tm_mday;
1571 hour2 = (*date).tm_hour;
1572 min2 = (*date).tm_min;
1573 sec2 = (*date).tm_sec;
1574 if (DateCalc_delta_ymdhms(year, month, day, hour, min, sec,
1575 year1,month1,day1, hour1,min1,sec1,
1576 year2,month2,day2, hour2,min2,sec2))
1577 {
1578 *dst = (*date).tm_isdst;
1579 if (*dst != 0)
1580 {
1581 if (*dst < 0) *dst = -1;
1582 else *dst = 1;
1583 }
1584 return(true);
1585 }
1586 }
1587 return(false);
1588 }
1589
1590 /* MacOS (Classic): */
1591 /* <695056.0> = Fri 1-Jan-1904 00:00:00 (time=0x00000000) */
1592 /* <744766.23295> = Mon 6-Feb-2040 06:28:15 (time=0xFFFFFFFF) */
1593
1594 /* Unix: */
1595 /* <719163.0> = Thu 1-Jan-1970 00:00:00 (time=0x00000000) */
1596 /* <744018.11647> = Tue 19-Jan-2038 03:14:07 (time=0x7FFFFFFF) */
1597
1598 #ifdef MACOS_TRADITIONAL
1599 #define DateCalc_DAYS_TO_EPOCH 695056L
1600 #define DateCalc_DAYS_TO_OVFLW 744766L
1601 #define DateCalc_SECS_TO_OVFLW 23295L
1602 #else
1603 #define DateCalc_DAYS_TO_EPOCH 719163L
1604 #define DateCalc_DAYS_TO_OVFLW 744018L
1605 #define DateCalc_SECS_TO_OVFLW 11647L
1606 #endif
1607
1608 /* Substitute for BSD's timegm(3) function: */
1609
DateCalc_date2time(time_t * seconds,Z_int year,Z_int month,Z_int day,Z_int hour,Z_int min,Z_int sec)1610 boolean DateCalc_date2time(time_t *seconds,
1611 Z_int year, Z_int month, Z_int day,
1612 Z_int hour, Z_int min, Z_int sec)
1613 {
1614 Z_long days;
1615 #ifdef MACOS_TRADITIONAL
1616 N_long secs;
1617 #else
1618 Z_long secs;
1619 #endif
1620
1621 *seconds = (time_t) 0;
1622
1623 days = DateCalc_Date_to_Days(year,month,day);
1624 secs = (((hour * 60L) + min) * 60L) + sec;
1625
1626 if ( (days < DateCalc_DAYS_TO_EPOCH) or
1627 #ifndef MACOS_TRADITIONAL
1628 (secs < 0L) or
1629 #endif
1630 (days > DateCalc_DAYS_TO_OVFLW) or
1631 ( (days == DateCalc_DAYS_TO_OVFLW) and (secs > DateCalc_SECS_TO_OVFLW) ) )
1632 return(false);
1633
1634 *seconds = (time_t) (((days - DateCalc_DAYS_TO_EPOCH) * 86400L) + secs);
1635 return(true);
1636 }
1637
1638 /* Substitute for POSIX's gmtime(3) function: */
1639
DateCalc_time2date(Z_int * year,Z_int * month,Z_int * day,Z_int * hour,Z_int * min,Z_int * sec,time_t seconds)1640 boolean DateCalc_time2date(Z_int *year, Z_int *month, Z_int *day,
1641 Z_int *hour, Z_int *min, Z_int *sec,
1642 time_t seconds)
1643 {
1644 #ifdef MACOS_TRADITIONAL
1645 N_long ss = (N_long) seconds;
1646 N_long mm;
1647 N_long hh;
1648 N_long dd;
1649
1650 dd = (N_long) (ss / 86400L);
1651 ss -= dd * 86400L;
1652 mm = (N_long) (ss / 60L);
1653 ss -= mm * 60L;
1654 hh = (N_long) (mm / 60L);
1655 #else
1656 Z_long ss = (Z_long) seconds;
1657 Z_long mm;
1658 Z_long hh;
1659 Z_long dd;
1660
1661 if (ss < 0L) return(false);
1662 dd = (Z_long) (ss / 86400L);
1663 ss -= dd * 86400L;
1664 mm = (Z_long) (ss / 60L);
1665 ss -= mm * 60L;
1666 hh = (Z_long) (mm / 60L);
1667 #endif
1668
1669 mm -= hh * 60L;
1670 dd += (DateCalc_DAYS_TO_EPOCH-1L);
1671 *sec = (Z_int) ss;
1672 *min = (Z_int) mm;
1673 *hour = (Z_int) hh;
1674 *day = (Z_int) 1;
1675 *month = (Z_int) 1;
1676 *year = (Z_int) 1;
1677 return( DateCalc_add_delta_days(year,month,day,dd) );
1678 }
1679
DateCalc_easter_sunday(Z_int * year,Z_int * month,Z_int * day)1680 boolean DateCalc_easter_sunday(Z_int *year, Z_int *month, Z_int *day)
1681 {
1682 /****************************************************************/
1683 /* */
1684 /* Gauss'sche Regel (Gaussian Rule) */
1685 /* ================================ */
1686 /* */
1687 /* Quelle / Source: */
1688 /* */
1689 /* H. H. Voigt, "Abriss der Astronomie", Wissenschaftsverlag, */
1690 /* Bibliographisches Institut, Seite 9. */
1691 /* */
1692 /****************************************************************/
1693
1694 Z_int a, b, c, d, e, m, n;
1695
1696 if ((*year < 1583) or (*year > 2299)) return(false);
1697
1698 if (*year < 1700) { m = 22; n = 2; }
1699 else if (*year < 1800) { m = 23; n = 3; }
1700 else if (*year < 1900) { m = 23; n = 4; }
1701 else if (*year < 2100) { m = 24; n = 5; }
1702 else if (*year < 2200) { m = 24; n = 6; }
1703 else { m = 25; n = 0; }
1704
1705 a = *year % 19;
1706 b = *year % 4;
1707 c = *year % 7;
1708 d = (19 * a + m) % 30;
1709 e = (2 * b + 4 * c + 6 * d + n) % 7;
1710 *day = 22 + d + e;
1711 *month = 3;
1712 if (*day > 31)
1713 {
1714 *day -= 31; /* same as *day = d + e - 9; */
1715 (*month)++;
1716 }
1717 if ((*day == 26) and (*month == 4)) *day = 19;
1718 if ((*day == 25) and (*month == 4) and
1719 (d == 28) and (e == 6) and (a > 10)) *day = 18;
1720 return(true);
1721 }
1722
1723 /* Carnival Monday / Rosenmontag / Veille du Mardi Gras = easter sunday - 48 */
1724 /* Mardi Gras / Karnevalsdienstag / Mardi Gras = easter sunday - 47 */
1725 /* Ash Wednesday / Aschermittwoch / Mercredi des Cendres = easter sunday - 46 */
1726 /* Palm Sunday / Palmsonntag / Dimanche des Rameaux = easter sunday - 7 */
1727 /* Easter Friday / Karfreitag / Vendredi Saint = easter sunday - 2 */
1728 /* Easter Saturday / Ostersamstag / Samedi de Paques = easter sunday - 1 */
1729 /* Easter Monday / Ostermontag / Lundi de Paques = easter sunday + 1 */
1730 /* Ascension of Christ / Christi Himmelfahrt / Ascension = easter sunday + 39 */
1731 /* Whitsunday / Pfingstsonntag / Dimanche de Pentecote = easter sunday + 49 */
1732 /* Whitmonday / Pfingstmontag / Lundi de Pentecote = easter sunday + 50 */
1733 /* Feast of Corpus Christi / Fronleichnam / Fete-Dieu = easter sunday + 60 */
1734
DateCalc_Decode_Month(charptr buffer,Z_int length,Z_int lang)1735 Z_int DateCalc_Decode_Month(charptr buffer, Z_int length, Z_int lang) /* 0 = error */
1736 {
1737 Z_int i,j;
1738 Z_int month;
1739 boolean same;
1740 boolean ok;
1741
1742 /*****************************************************************************/
1743 /* BEWARE that the parameter "length" must always be set in such a way */
1744 /* so that the string in "buffer[0]" up to "buffer[length-1]" does not */
1745 /* contain any terminating null character '\0'. Otherwise this routine */
1746 /* may read beyond allocated memory, probably resulting in an access */
1747 /* violation and program abortion. This problem cannot arise, for example, */
1748 /* if you use the library function "strlen" to determine the length */
1749 /* "length" of the string in "buffer". */
1750 /*****************************************************************************/
1751
1752 if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
1753 month = 0;
1754 ok = true;
1755 for ( i = 1; ok and (i <= 12); i++ )
1756 {
1757 same = true;
1758 for ( j = 0; same and (j < length); j++ )
1759 {
1760 same = ( DateCalc_ISO_UC(buffer[j]) ==
1761 DateCalc_ISO_UC(DateCalc_Month_to_Text_[lang][i][j]) );
1762 }
1763 if (same)
1764 {
1765 if (month > 0) ok = false;
1766 else month = i;
1767 }
1768 }
1769 if (ok) return(month);
1770 else return(0);
1771 }
1772
DateCalc_Decode_Day_of_Week(charptr buffer,Z_int length,Z_int lang)1773 Z_int DateCalc_Decode_Day_of_Week(charptr buffer, Z_int length, Z_int lang) /* 0 = error */
1774 {
1775 Z_int i,j;
1776 Z_int day;
1777 boolean same;
1778 boolean ok;
1779
1780 /*****************************************************************************/
1781 /* BEWARE that the parameter "length" must always be set in such a way */
1782 /* so that the string in "buffer[0]" up to "buffer[length-1]" does not */
1783 /* contain any terminating null character '\0'. Otherwise this routine */
1784 /* may read beyond allocated memory, probably resulting in an access */
1785 /* violation and program abortion. This problem cannot arise, for example, */
1786 /* if you use the library function "strlen" to determine the length */
1787 /* "length" of the string in "buffer". */
1788 /*****************************************************************************/
1789
1790 if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
1791 day = 0;
1792 ok = true;
1793 for ( i = 1; ok and (i <= 7); i++ )
1794 {
1795 same = true;
1796 for ( j = 0; same and (j < length); j++ )
1797 {
1798 same = ( DateCalc_ISO_UC(buffer[j]) ==
1799 DateCalc_ISO_UC(DateCalc_Day_of_Week_to_Text_[lang][i][j]) );
1800 }
1801 if (same)
1802 {
1803 if (day > 0) ok = false;
1804 else day = i;
1805 }
1806 }
1807 if (ok) return(day);
1808 else return(0);
1809 }
1810
DateCalc_Decode_Language(charptr buffer,Z_int length)1811 Z_int DateCalc_Decode_Language(charptr buffer, Z_int length) /* 0 = error */
1812 {
1813 Z_int i,j;
1814 Z_int lang;
1815 boolean same;
1816 boolean ok;
1817
1818 /*****************************************************************************/
1819 /* BEWARE that the parameter "length" must always be set in such a way */
1820 /* so that the string in "buffer[0]" up to "buffer[length-1]" does not */
1821 /* contain any terminating null character '\0'. Otherwise this routine */
1822 /* may read beyond allocated memory, probably resulting in an access */
1823 /* violation and program abortion. This problem cannot arise, for example, */
1824 /* if you use the library function "strlen" to determine the length */
1825 /* "length" of the string in "buffer". */
1826 /*****************************************************************************/
1827
1828 lang = 0;
1829 ok = true;
1830 for ( i = 1; ok and (i <= DateCalc_LANGUAGES); i++ )
1831 {
1832 same = true;
1833 for ( j = 0; same and (j < length); j++ )
1834 {
1835 same = ( DateCalc_ISO_UC(buffer[j]) ==
1836 DateCalc_ISO_UC(DateCalc_Language_to_Text_[i][j]) );
1837 }
1838 if (same)
1839 {
1840 if (lang > 0) ok = false;
1841 else lang = i;
1842 }
1843 }
1844 if (ok) return(lang);
1845 else return(0);
1846 }
1847
DateCalc_decode_date_eu(charptr buffer,Z_int * year,Z_int * month,Z_int * day,Z_int lang)1848 boolean DateCalc_decode_date_eu(charptr buffer,
1849 Z_int *year, Z_int *month, Z_int *day, Z_int lang)
1850 {
1851 Z_int i,j;
1852 Z_int length;
1853
1854 if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
1855 *year = *month = *day = 0;
1856 length = strlen((char *)buffer);
1857 if (length > 0)
1858 {
1859 i = 0;
1860 while (DateCalc_scan9(buffer,length,i,true)) i++;
1861 j = length-1;
1862 while (DateCalc_scan9(buffer,length,j,true)) j--;
1863 if (i+1 < j) /* at least 3 chars, else error! */
1864 {
1865 buffer += i;
1866 length = j-i+1;
1867 i = 1;
1868 while (DateCalc_scan9(buffer,length,i,false)) i++;
1869 j = length-2;
1870 while (DateCalc_scan9(buffer,length,j,false)) j--;
1871 if (j < i) /* only numerical chars without delimiters */
1872 {
1873 switch (length)
1874 {
1875 case 3:
1876 *day = DateCalc_Str2Int(buffer, 1);
1877 *month = DateCalc_Str2Int(buffer+1,1);
1878 *year = DateCalc_Str2Int(buffer+2,1);
1879 break;
1880 case 4:
1881 *day = DateCalc_Str2Int(buffer, 1);
1882 *month = DateCalc_Str2Int(buffer+1,1);
1883 *year = DateCalc_Str2Int(buffer+2,2);
1884 break;
1885 case 5:
1886 *day = DateCalc_Str2Int(buffer, 1);
1887 *month = DateCalc_Str2Int(buffer+1,2);
1888 *year = DateCalc_Str2Int(buffer+3,2);
1889 break;
1890 case 6:
1891 *day = DateCalc_Str2Int(buffer, 2);
1892 *month = DateCalc_Str2Int(buffer+2,2);
1893 *year = DateCalc_Str2Int(buffer+4,2);
1894 break;
1895 case 7:
1896 *day = DateCalc_Str2Int(buffer, 1);
1897 *month = DateCalc_Str2Int(buffer+1,2);
1898 *year = DateCalc_Str2Int(buffer+3,4);
1899 break;
1900 case 8:
1901 *day = DateCalc_Str2Int(buffer, 2);
1902 *month = DateCalc_Str2Int(buffer+2,2);
1903 *year = DateCalc_Str2Int(buffer+4,4);
1904 break;
1905 default:
1906 return(false);
1907 break;
1908 }
1909 }
1910 else /* at least one non-numerical char (i <= j) */
1911 {
1912 *day = DateCalc_Str2Int(buffer,i);
1913 *year = DateCalc_Str2Int(buffer+(j+1),length-(j+1));
1914 while (DateCalc_scanx(buffer,length,i,true)) i++;
1915 while (DateCalc_scanx(buffer,length,j,true)) j--;
1916 if (i <= j) /* at least one char left for month */
1917 {
1918 buffer += i;
1919 length = j-i+1;
1920 i = 1;
1921 while (DateCalc_scanx(buffer,length,i,false)) i++;
1922 if (i >= length) /* ok, no more delimiters */
1923 {
1924 i = 0;
1925 while (DateCalc_scan9(buffer,length,i,false)) i++;
1926 if (i >= length) /* only digits for month */
1927 {
1928 *month = DateCalc_Str2Int(buffer,length);
1929 }
1930 else /* match with month names */
1931 {
1932 *month = DateCalc_Decode_Month(buffer,length,lang);
1933 }
1934 }
1935 else return(false); /* delimiters inside month string */
1936 }
1937 else return(false); /* no chars left for month */
1938 } /* at least one non-numerical char (i <= j) */
1939 }
1940 else return(false); /* less than 3 chars in buffer */
1941 }
1942 else return(false); /* length <= 0 */
1943 *year = DateCalc_Moving_Window(*year);
1944 return( DateCalc_check_date(*year,*month,*day) );
1945 }
1946
DateCalc_decode_date_us(charptr buffer,Z_int * year,Z_int * month,Z_int * day,Z_int lang)1947 boolean DateCalc_decode_date_us(charptr buffer,
1948 Z_int *year, Z_int *month, Z_int *day, Z_int lang)
1949 {
1950 Z_int i,j,k;
1951 Z_int length;
1952
1953 if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
1954 *year = *month = *day = 0;
1955 length = strlen((char *)buffer);
1956 if (length > 0)
1957 {
1958 i = 0;
1959 while (DateCalc_scanx(buffer,length,i,true)) i++;
1960 j = length-1;
1961 while (DateCalc_scan9(buffer,length,j,true)) j--;
1962 if (i+1 < j) /* at least 3 chars, else error! */
1963 {
1964 buffer += i;
1965 length = j-i+1;
1966 i = 1;
1967 while (DateCalc_scanx(buffer,length,i,false)) i++;
1968 j = length-2;
1969 while (DateCalc_scan9(buffer,length,j,false)) j--;
1970 if (i >= length) /* only alphanumeric chars left */
1971 {
1972 if (j < 0) /* case 0 : xxxx999999xxxx */
1973 { /* j0 i */
1974 switch (length)
1975 {
1976 case 3:
1977 *month = DateCalc_Str2Int(buffer, 1);
1978 *day = DateCalc_Str2Int(buffer+1,1);
1979 *year = DateCalc_Str2Int(buffer+2,1);
1980 break;
1981 case 4:
1982 *month = DateCalc_Str2Int(buffer, 1);
1983 *day = DateCalc_Str2Int(buffer+1,1);
1984 *year = DateCalc_Str2Int(buffer+2,2);
1985 break;
1986 case 5:
1987 *month = DateCalc_Str2Int(buffer, 1);
1988 *day = DateCalc_Str2Int(buffer+1,2);
1989 *year = DateCalc_Str2Int(buffer+3,2);
1990 break;
1991 case 6:
1992 *month = DateCalc_Str2Int(buffer, 2);
1993 *day = DateCalc_Str2Int(buffer+2,2);
1994 *year = DateCalc_Str2Int(buffer+4,2);
1995 break;
1996 case 7:
1997 *month = DateCalc_Str2Int(buffer, 1);
1998 *day = DateCalc_Str2Int(buffer+1,2);
1999 *year = DateCalc_Str2Int(buffer+3,4);
2000 break;
2001 case 8:
2002 *month = DateCalc_Str2Int(buffer, 2);
2003 *day = DateCalc_Str2Int(buffer+2,2);
2004 *year = DateCalc_Str2Int(buffer+4,4);
2005 break;
2006 default:
2007 return(false);
2008 break;
2009 }
2010 }
2011 else /* case 1 : xxxxAAA999999xxxx */
2012 { /* 0 j i */
2013 *month = DateCalc_Decode_Month(buffer,j+1,lang);
2014 buffer += j+1;
2015 length -= j+1;
2016 switch (length)
2017 {
2018 case 2:
2019 *day = DateCalc_Str2Int(buffer, 1);
2020 *year = DateCalc_Str2Int(buffer+1,1);
2021 break;
2022 case 3:
2023 *day = DateCalc_Str2Int(buffer, 1);
2024 *year = DateCalc_Str2Int(buffer+1,2);
2025 break;
2026 case 4:
2027 *day = DateCalc_Str2Int(buffer, 2);
2028 *year = DateCalc_Str2Int(buffer+2,2);
2029 break;
2030 case 5:
2031 *day = DateCalc_Str2Int(buffer, 1);
2032 *year = DateCalc_Str2Int(buffer+1,4);
2033 break;
2034 case 6:
2035 *day = DateCalc_Str2Int(buffer, 2);
2036 *year = DateCalc_Str2Int(buffer+2,4);
2037 break;
2038 default:
2039 return(false);
2040 break;
2041 }
2042 }
2043 } /* 0 i j l */
2044 else /* case 2 : xxxxAAAxxxx9999xxxx _OR_ */
2045 { /* case 3 : xxxxAAAxx99xx9999xx */
2046 k = 0; /* 0 i j l */
2047 while (DateCalc_scan9(buffer,length,k,false)) k++;
2048 if (k >= i) /* ok, only digits */
2049 {
2050 *month = DateCalc_Str2Int(buffer,i);
2051 }
2052 else /* no, some non-digits */
2053 {
2054 *month = DateCalc_Decode_Month(buffer,i,lang);
2055 if (*month == 0) return(false);
2056 }
2057 buffer += i;
2058 length -= i;
2059 j -= i;
2060 k = j+1; /* remember start posn of day+year(2)/year(3) */
2061 i = 1;
2062 while (DateCalc_scanx(buffer,length,i,true)) i++;
2063 j--;
2064 while (DateCalc_scan9(buffer,length,j,true)) j--;
2065 if (j < i) /* case 2 : xxxxAAAxxxx9999xxxx */
2066 { /* j0 i l */
2067 buffer += k; /* k */
2068 length -= k;
2069 switch (length)
2070 {
2071 case 2:
2072 *day = DateCalc_Str2Int(buffer, 1);
2073 *year = DateCalc_Str2Int(buffer+1,1);
2074 break;
2075 case 3:
2076 *day = DateCalc_Str2Int(buffer, 1);
2077 *year = DateCalc_Str2Int(buffer+1,2);
2078 break;
2079 case 4:
2080 *day = DateCalc_Str2Int(buffer, 2);
2081 *year = DateCalc_Str2Int(buffer+2,2);
2082 break;
2083 case 5:
2084 *day = DateCalc_Str2Int(buffer, 1);
2085 *year = DateCalc_Str2Int(buffer+1,4);
2086 break;
2087 case 6:
2088 *day = DateCalc_Str2Int(buffer, 2);
2089 *year = DateCalc_Str2Int(buffer+2,4);
2090 break;
2091 default:
2092 return(false);
2093 break;
2094 }
2095 }
2096 else /* case 3 : xxxxAAAxx99xx9999xx */
2097 { /* 0 ij k l */
2098 *year = DateCalc_Str2Int(buffer+k,length-k);
2099 k = i;
2100 while (DateCalc_scan9(buffer,length,k,false)) k++;
2101 if (k > j) /* ok, only digits */
2102 {
2103 *day = DateCalc_Str2Int(buffer+i,j-i+1);
2104 }
2105 else return(false); /* non-digits inside day */
2106 }
2107 } /* i < length */
2108 }
2109 else return(false); /* less than 3 chars in buffer */
2110 }
2111 else return(false); /* length <= 0 */
2112 *year = DateCalc_Moving_Window(*year);
2113 return( DateCalc_check_date(*year,*month,*day) );
2114 }
2115
DateCalc_Fixed_Window(Z_int year)2116 Z_int DateCalc_Fixed_Window(Z_int year)
2117 {
2118 if (year < 0) return(0);
2119 if (year < 100)
2120 {
2121 if (year < DateCalc_YEAR_OF_EPOCH) year += 100;
2122 year += DateCalc_CENTURY_OF_EPOCH;
2123 }
2124 return(year);
2125 }
2126
DateCalc_Moving_Window(Z_int year)2127 Z_int DateCalc_Moving_Window(Z_int year)
2128 {
2129 time_t seconds;
2130 struct tm *date;
2131 Z_int current;
2132 Z_int century;
2133
2134 if (year < 0) return(0);
2135 if (year < 100)
2136 {
2137 if ((time(&seconds) >= 0) and ((date = gmtime(&seconds)) != NULL))
2138 {
2139 current = (*date).tm_year + 1900;
2140 century = (Z_int)(current / 100);
2141 year += century * 100;
2142 if (year < current - 50) year += 100;
2143 else if (year >= current + 50) year -= 100;
2144 }
2145 else year = DateCalc_Fixed_Window(year);
2146 }
2147 return(year);
2148 }
2149
DateCalc_Compress(Z_int year,Z_int month,Z_int day)2150 Z_int DateCalc_Compress(Z_int year, Z_int month, Z_int day)
2151 {
2152 Z_int yy;
2153
2154 if ((year >= DateCalc_EPOCH) and (year < (DateCalc_EPOCH + 100)))
2155 {
2156 yy = year;
2157 year -= DateCalc_EPOCH;
2158 }
2159 else
2160 {
2161 if ((year < 0) or (year > 99)) return(0);
2162 if (year < DateCalc_YEAR_OF_EPOCH)
2163 {
2164 yy = DateCalc_CENTURY_OF_EPOCH + 100 + year;
2165 year += 100 - DateCalc_YEAR_OF_EPOCH;
2166 }
2167 else
2168 {
2169 yy = DateCalc_CENTURY_OF_EPOCH + year;
2170 year -= DateCalc_YEAR_OF_EPOCH;
2171 }
2172 }
2173 if ((month < 1) or (month > 12)) return(0);
2174 if ((day < 1) or
2175 (day > DateCalc_Days_in_Month_[DateCalc_leap_year(yy)][month]))
2176 return(0);
2177 return( (year SHL 9) OR (month SHL 5) OR day );
2178 }
2179
2180 boolean
DateCalc_uncompress(Z_int date,Z_int * century,Z_int * year,Z_int * month,Z_int * day)2181 DateCalc_uncompress(Z_int date,
2182 Z_int *century, Z_int *year, Z_int *month, Z_int *day)
2183 {
2184 if (date > 0)
2185 {
2186 *year = date SHR 9;
2187 *month = (date AND 0x01FF) SHR 5;
2188 *day = date AND 0x001F;
2189
2190 if (*year < 100)
2191 {
2192 if (*year < 100-DateCalc_YEAR_OF_EPOCH)
2193 {
2194 *century = DateCalc_CENTURY_OF_EPOCH;
2195 *year += DateCalc_YEAR_OF_EPOCH;
2196 }
2197 else
2198 {
2199 *century = DateCalc_CENTURY_OF_EPOCH+100;
2200 *year -= 100-DateCalc_YEAR_OF_EPOCH;
2201 }
2202 return( DateCalc_check_date(*century+*year,*month,*day) );
2203 }
2204 }
2205 return(false);
2206 }
2207
DateCalc_check_compressed(Z_int date)2208 boolean DateCalc_check_compressed(Z_int date)
2209 {
2210 Z_int century;
2211 Z_int year;
2212 Z_int month;
2213 Z_int day;
2214
2215 return( DateCalc_uncompress(date,¢ury,&year,&month,&day) );
2216 }
2217
DateCalc_Compressed_to_Text(Z_int date,Z_int lang)2218 charptr DateCalc_Compressed_to_Text(Z_int date, Z_int lang)
2219 {
2220 Z_int century;
2221 Z_int year;
2222 Z_int month;
2223 Z_int day;
2224 charptr string;
2225
2226 if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
2227 string = (charptr) malloc(16);
2228 if (string == NULL) return(NULL);
2229 if (DateCalc_uncompress(date,¢ury,&year,&month,&day))
2230 sprintf((char *)string,"%02d-%.3s-%02d",day,
2231 DateCalc_Month_to_Text_[lang][month],year);
2232 else
2233 sprintf((char *)string,"??""-???""-??");
2234 /* prevent interpretation as trigraphs */
2235 return(string);
2236 }
2237
DateCalc_Date_to_Text(Z_int year,Z_int month,Z_int day,Z_int lang)2238 charptr DateCalc_Date_to_Text(Z_int year, Z_int month, Z_int day, Z_int lang)
2239 {
2240 charptr string;
2241
2242 if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
2243 if (DateCalc_check_date(year,month,day) and
2244 ((string = (charptr) malloc(32)) != NULL))
2245 {
2246 if (DateCalc_Day_of_Week_Abbreviation_[lang][0][0] != '\0')
2247 {
2248 sprintf((char *)string,"%.3s %d-%.3s-%d",
2249 DateCalc_Day_of_Week_Abbreviation_[lang][DateCalc_Day_of_Week(year,month,day)],
2250 day,DateCalc_Month_to_Text_[lang][month],year);
2251 return(string);
2252 }
2253 else
2254 {
2255 sprintf((char *)string,"%.3s %d-%.3s-%d",
2256 DateCalc_Day_of_Week_to_Text_[lang][DateCalc_Day_of_Week(year,month,day)],
2257 day,DateCalc_Month_to_Text_[lang][month],year);
2258 return(string);
2259 }
2260 }
2261 return(NULL);
2262 }
2263
DateCalc_English_Ordinal(charptr result,Z_int number)2264 charptr DateCalc_English_Ordinal(charptr result, Z_int number)
2265 {
2266 N_int length;
2267 N_int digit;
2268
2269 sprintf((char *)result, "%d", number);
2270 if ((length = strlen((char *)result)))
2271 {
2272 if ( not
2273 (
2274 ( ((length > 1) and (result[length-2] != '1')) or (length == 1) )
2275 and
2276 ( (digit = (N_int)(result[length-1] XOR '0')) <= 3 )
2277 )
2278 )
2279 {
2280 digit = 0;
2281 }
2282 sprintf( (char *)(result+length), "%s",
2283 DateCalc_English_Ordinals_[digit] );
2284 }
2285 return(result);
2286 }
2287
DateCalc_Date_to_Text_Long(Z_int year,Z_int month,Z_int day,Z_int lang)2288 charptr DateCalc_Date_to_Text_Long(Z_int year, Z_int month, Z_int day, Z_int lang)
2289 {
2290 charptr string;
2291 blockdef(buffer,64);
2292
2293 if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
2294 if (DateCalc_check_date(year,month,day) and
2295 ((string = (charptr) malloc(64)) != NULL))
2296 {
2297 switch (lang)
2298 {
2299 case 1:
2300 sprintf(
2301 (char *)string,
2302 (char *)DateCalc_Date_Long_Format_[lang],
2303 DateCalc_Day_of_Week_to_Text_[lang]
2304 [DateCalc_Day_of_Week(year,month,day)],
2305 DateCalc_Month_to_Text_[lang][month],
2306 DateCalc_English_Ordinal(buffer,day),
2307 year );
2308 break;
2309 case 12:
2310 sprintf(
2311 (char *)string,
2312 (char *)DateCalc_Date_Long_Format_[lang],
2313 year,
2314 DateCalc_Month_to_Text_[lang][month],
2315 day,
2316 DateCalc_Day_of_Week_to_Text_[lang]
2317 [DateCalc_Day_of_Week(year,month,day)] );
2318 break;
2319 default:
2320 sprintf(
2321 (char *)string,
2322 (char *)DateCalc_Date_Long_Format_[lang],
2323 DateCalc_Day_of_Week_to_Text_[lang]
2324 [DateCalc_Day_of_Week(year,month,day)],
2325 day,
2326 DateCalc_Month_to_Text_[lang][month],
2327 year );
2328 break;
2329 }
2330 return(string);
2331 }
2332 return(NULL);
2333 }
2334
DateCalc_Calendar(Z_int year,Z_int month,boolean orthodox,Z_int lang)2335 charptr DateCalc_Calendar(Z_int year, Z_int month, boolean orthodox, Z_int lang)
2336 {
2337 blockdef(buffer,64);
2338 charptr string;
2339 charptr cursor;
2340 Z_int first;
2341 Z_int last;
2342 Z_int day;
2343
2344 if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language;
2345 string = (charptr) malloc(256);
2346 if (string == NULL) return(NULL);
2347 cursor = string;
2348 DateCalc_Newline(&cursor,1);
2349 sprintf((char *)buffer,"%s %d",
2350 DateCalc_Month_to_Text_[lang][month],year);
2351 *buffer = DateCalc_ISO_UC(*buffer);
2352 DateCalc_Center(&cursor,buffer,27);
2353 if (DateCalc_Day_of_Week_Abbreviation_[lang][0][0] != '\0')
2354 {
2355 if (orthodox)
2356 sprintf((char *)cursor,"%3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s\n",
2357 DateCalc_Day_of_Week_Abbreviation_[lang][7],
2358 DateCalc_Day_of_Week_Abbreviation_[lang][1],
2359 DateCalc_Day_of_Week_Abbreviation_[lang][2],
2360 DateCalc_Day_of_Week_Abbreviation_[lang][3],
2361 DateCalc_Day_of_Week_Abbreviation_[lang][4],
2362 DateCalc_Day_of_Week_Abbreviation_[lang][5],
2363 DateCalc_Day_of_Week_Abbreviation_[lang][6]);
2364 else /* conform to ISO standard */
2365 sprintf((char *)cursor,"%3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s\n",
2366 DateCalc_Day_of_Week_Abbreviation_[lang][1],
2367 DateCalc_Day_of_Week_Abbreviation_[lang][2],
2368 DateCalc_Day_of_Week_Abbreviation_[lang][3],
2369 DateCalc_Day_of_Week_Abbreviation_[lang][4],
2370 DateCalc_Day_of_Week_Abbreviation_[lang][5],
2371 DateCalc_Day_of_Week_Abbreviation_[lang][6],
2372 DateCalc_Day_of_Week_Abbreviation_[lang][7]);
2373 }
2374 else
2375 {
2376 if (orthodox)
2377 sprintf((char *)cursor,"%3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s\n",
2378 DateCalc_Day_of_Week_to_Text_[lang][7],
2379 DateCalc_Day_of_Week_to_Text_[lang][1],
2380 DateCalc_Day_of_Week_to_Text_[lang][2],
2381 DateCalc_Day_of_Week_to_Text_[lang][3],
2382 DateCalc_Day_of_Week_to_Text_[lang][4],
2383 DateCalc_Day_of_Week_to_Text_[lang][5],
2384 DateCalc_Day_of_Week_to_Text_[lang][6]);
2385 else /* conform to ISO standard */
2386 sprintf((char *)cursor,"%3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s\n",
2387 DateCalc_Day_of_Week_to_Text_[lang][1],
2388 DateCalc_Day_of_Week_to_Text_[lang][2],
2389 DateCalc_Day_of_Week_to_Text_[lang][3],
2390 DateCalc_Day_of_Week_to_Text_[lang][4],
2391 DateCalc_Day_of_Week_to_Text_[lang][5],
2392 DateCalc_Day_of_Week_to_Text_[lang][6],
2393 DateCalc_Day_of_Week_to_Text_[lang][7]);
2394 }
2395 cursor += 28;
2396 first = DateCalc_Day_of_Week(year,month,1);
2397 last = DateCalc_Days_in_Month_[DateCalc_leap_year(year)][month];
2398 if (orthodox) { if (first == 7) first = 0; }
2399 else { first--; }
2400 if (first) DateCalc_Blank(&cursor,(first<<2)-1);
2401 for ( day = 1; day <= last; day++, first++ )
2402 {
2403 if (first > 0)
2404 {
2405 if (first > 6)
2406 {
2407 first = 0;
2408 DateCalc_Newline(&cursor,1);
2409 }
2410 else DateCalc_Blank(&cursor,1);
2411 }
2412 sprintf((char *)cursor," %2d",day);
2413 cursor += 3;
2414 }
2415 DateCalc_Newline(&cursor,2);
2416 return(string);
2417 }
2418
DateCalc_Dispose(charptr string)2419 void DateCalc_Dispose(charptr string)
2420 {
2421 free((voidptr) string);
2422 }
2423
DateCalc_Version(void)2424 charptr DateCalc_Version(void)
2425 {
2426 return( (charptr) "6.4" );
2427 }
2428
2429 /*****************************************************************************/
2430 /* VERSION: 6.4 */
2431 /*****************************************************************************/
2432 /* VERSION HISTORY: */
2433 /*****************************************************************************/
2434 /* */
2435 /* Version 6.4 07.03.15 No changes. */
2436 /* Version 6.3 17.05.12 No changes. */
2437 /* Version 6.2 16.10.09 No changes. */
2438 /* Version 6.1 15.10.09 Fixed Polish language entries. */
2439 /* Version 6.0 07.10.09 +: norm_delta_ymdhms, add_norm_delta_ymd[hms]. */
2440 /* Version 5.8 12.09.09 Added "norm_delta_ymd()". */
2441 /* Version 5.7 23.08.09 Fixed Dutch "oktober", Portuguese DOW abbrevs. */
2442 /* Version 5.6 28.07.09 Made the module MacOS X compatible. */
2443 /* Version 5.5 skipped due to an unauthorized upload by someone else. */
2444 /* Version 5.4 03.10.04 Added compiler directives for C++. */
2445 /* Version 5.3 29.09.02 No changes. */
2446 /* Version 5.2 18.09.02 No changes. */
2447 /* Version 5.1 08.09.02 Added conditional changes for MacOS/MacPerl. */
2448 /* Version 5.0 10.10.01 New YMD/HMS functions, replaced <ctype.h>, ... */
2449 /* Version 4.3 08.01.00 decode_date_??: (yy < 70 ? 20yy : 19yy) */
2450 /* Version 4.2 07.09.98 No changes. */
2451 /* Version 4.1 08.06.98 Fixed bug in "add_delta_ymd()". */
2452 /* Version 4.0 12.05.98 Major rework. Added multi-language support. */
2453 /* Version 3.2 15.06.97 Added "week_of_year()". */
2454 /* Version 3.1 12.06.97 No significant changes. */
2455 /* Version 3.0 16.02.97 Changed conventions for unsuccessful returns. */
2456 /* Version 2.3 22.11.96 Fixed unbalanced "malloc" and "free". */
2457 /* Version 2.2 26.05.96 No significant changes. */
2458 /* Version 2.1 26.05.96 Fixed HH MM SS parameter checks. */
2459 /* Version 2.0 25.05.96 Added time calculations. Major rework. */
2460 /* Version 1.6 20.04.96 Not published. */
2461 /* Version 1.5 14.03.96 No significant changes. */
2462 /* Version 1.4 11.02.96 No significant changes. */
2463 /* Version 1.3 10.12.95 Added "days_in_month()". */
2464 /* Version 1.2b 27.11.95 No significant changes. */
2465 /* Version 1.2a 21.11.95 Fix for type name clashes. */
2466 /* Version 1.1 18.11.95 Fix for type name clashes. */
2467 /* Version 1.01 16.11.95 Improved compliance w/ programming standards. */
2468 /* Version 1.0 14.11.95 First version under UNIX (with Perl module). */
2469 /* Version 0.9 01.11.93 First version of C library under MS-DOS. */
2470 /* */
2471 /*****************************************************************************/
2472 /* AUTHOR: */
2473 /*****************************************************************************/
2474 /* */
2475 /* Steffen Beyer */
2476 /* mailto:STBEY@cpan.org */
2477 /* http://www.engelschall.com/u/sb/download/ */
2478 /* */
2479 /*****************************************************************************/
2480 /* COPYRIGHT: */
2481 /*****************************************************************************/
2482 /* */
2483 /* Copyright (c) 1993 - 2015 by Steffen Beyer. */
2484 /* All rights reserved. */
2485 /* */
2486 /*****************************************************************************/
2487 /* LICENSE: */
2488 /*****************************************************************************/
2489 /* */
2490 /* This library is free software; you can redistribute it and/or */
2491 /* modify it under the terms of the GNU Library General Public */
2492 /* License as published by the Free Software Foundation; either */
2493 /* version 2 of the License, or (at your option) any later version. */
2494 /* */
2495 /* This library is distributed in the hope that it will be useful, */
2496 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
2497 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
2498 /* Library General Public License for more details. */
2499 /* */
2500 /* You should have received a copy of the GNU Library General Public */
2501 /* License along with this library; if not, write to the */
2502 /* Free Software Foundation, Inc., */
2503 /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
2504 /* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */
2505 /* */
2506 /*****************************************************************************/
2507 #endif
2508