#ifndef MODULE_DATE_CALC #define MODULE_DATE_CALC /*****************************************************************************/ /* MODULE NAME: DatePcalc.c MODULE TYPE: (lib) */ /*****************************************************************************/ /* Gregorian calendar date calculations in compliance with */ /* ISO/R 2015-1971, DIN 1355 and (to some extent) ISO 8601. */ /*****************************************************************************/ /* MODULE IMPORTS: */ /*****************************************************************************/ #include /* MODULE TYPE: (sys) */ #include /* MODULE TYPE: (sys) */ #include /* MODULE TYPE: (sys) */ #include /* MODULE TYPE: (sys) */ #include "ToolBox.h" /* MODULE TYPE: (dat) */ /*****************************************************************************/ /* MODULE INTERFACE: */ /*****************************************************************************/ /* Make the VMS linker happy: */ #ifdef VMS #define DateCalc_Day_of_Week_Abbreviation_ DateCalc_DoW_Abbrev_ #define DateCalc_nth_weekday_of_month_year DateCalc_nth_weekday #endif boolean DateCalc_leap_year (Z_int year); boolean DateCalc_check_date (Z_int year, Z_int month, Z_int day); boolean DateCalc_check_time (Z_int hour, Z_int min, Z_int sec); boolean DateCalc_check_business_date (Z_int year, Z_int week, Z_int dow); Z_int DateCalc_Day_of_Year (Z_int year, Z_int month, Z_int day); Z_long DateCalc_Date_to_Days (Z_int year, Z_int month, Z_int day); Z_int DateCalc_Day_of_Week (Z_int year, Z_int month, Z_int day); Z_int DateCalc_Weeks_in_Year (Z_int year); Z_int DateCalc_Week_Number (Z_int year, Z_int month, Z_int day); boolean DateCalc_week_of_year (Z_int *week, /* O */ Z_int *year, /* I/O */ Z_int month, /* I */ Z_int day); /* I */ boolean DateCalc_monday_of_week (Z_int week, /* I */ Z_int *year, /* I/O */ Z_int *month, /* O */ Z_int *day); /* O */ boolean DateCalc_nth_weekday_of_month_year (Z_int *year, /* I/O */ Z_int *month, /* I/O */ Z_int *day, /* O */ Z_int dow, /* I */ Z_int n); /* I */ boolean DateCalc_standard_to_business (Z_int *year, /* I/O */ Z_int *week, /* O */ Z_int *dow, /* O */ Z_int month, /* I */ Z_int day); /* I */ boolean DateCalc_business_to_standard (Z_int *year, /* I/O */ Z_int *month, /* O */ Z_int *day, /* O */ Z_int week, /* I */ Z_int dow); /* I */ Z_long DateCalc_Delta_Days (Z_int year1, Z_int month1, Z_int day1, Z_int year2, Z_int month2, Z_int day2); boolean /* PRIVATE */ DateCalc_delta_hms (Z_long *Dd, /* I/O */ Z_int *Dh, /* O */ Z_int *Dm, /* O */ Z_int *Ds, /* O */ Z_int hour1, /* I */ Z_int min1, /* I */ Z_int sec1, /* I */ Z_int hour2, /* I */ Z_int min2, /* I */ Z_int sec2); /* I */ boolean DateCalc_delta_dhms (Z_long *Dd, /* O */ Z_int *Dh, /* O */ Z_int *Dm, /* O */ Z_int *Ds, /* O */ Z_int year1, /* I */ Z_int month1, /* I */ Z_int day1, /* I */ Z_int hour1, /* I */ Z_int min1, /* I */ Z_int sec1, /* I */ Z_int year2, /* I */ Z_int month2, /* I */ Z_int day2, /* I */ Z_int hour2, /* I */ Z_int min2, /* I */ Z_int sec2); /* I */ boolean DateCalc_delta_ymd (Z_int *year1, /* I/O */ Z_int *month1, /* I/O */ Z_int *day1, /* I/O */ Z_int year2, /* I */ Z_int month2, /* I */ Z_int day2); /* I */ boolean DateCalc_delta_ymdhms (Z_int *D_y, /* O */ Z_int *D_m, /* O */ Z_int *D_d, /* O */ Z_int *Dh, /* O */ Z_int *Dm, /* O */ Z_int *Ds, /* O */ Z_int year1, /* I */ Z_int month1, /* I */ Z_int day1, /* I */ Z_int hour1, /* I */ Z_int min1, /* I */ Z_int sec1, /* I */ Z_int year2, /* I */ Z_int month2, /* I */ Z_int day2, /* I */ Z_int hour2, /* I */ Z_int min2, /* I */ Z_int sec2); /* I */ boolean DateCalc_norm_delta_ymd (Z_int *year1, /* I/O */ Z_int *month1, /* I/O */ Z_int *day1, /* I/O */ Z_int year2, /* I */ Z_int month2, /* I */ Z_int day2); /* I */ boolean DateCalc_norm_delta_ymdhms (Z_int *D_y, /* O */ Z_int *D_m, /* O */ Z_int *D_d, /* O */ Z_int *Dhh, /* O */ Z_int *Dmm, /* O */ Z_int *Dss, /* O */ Z_int year1, /* I */ Z_int month1, /* I */ Z_int day1, /* I */ Z_int hour1, /* I */ Z_int min1, /* I */ Z_int sec1, /* I */ Z_int year2, /* I */ Z_int month2, /* I */ Z_int day2, /* I */ Z_int hour2, /* I */ Z_int min2, /* I */ Z_int sec2); /* I */ void DateCalc_Normalize_DHMS (Z_long *Dd, /* I/O */ Z_long *Dh, /* I/O */ Z_long *Dm, /* I/O */ Z_long *Ds); /* I/O */ boolean DateCalc_add_delta_days (Z_int *year, /* I/O */ Z_int *month, /* I/O */ Z_int *day, /* I/O */ Z_long Dd); /* I */ boolean DateCalc_add_delta_dhms (Z_int *year, /* I/O */ Z_int *month, /* I/O */ Z_int *day, /* I/O */ Z_int *hour, /* I/O */ Z_int *min, /* I/O */ Z_int *sec, /* I/O */ Z_long Dd, /* I */ Z_long Dh, /* I */ Z_long Dm, /* I */ Z_long Ds); /* I */ boolean /* PRIVATE */ DateCalc_add_year_month (Z_int *year, /* I/O */ Z_int *month, /* I/O */ Z_long Dy, /* I */ Z_long Dm); /* I */ boolean DateCalc_add_delta_ym (Z_int *year, /* I/O */ Z_int *month, /* I/O */ Z_int *day, /* I/O */ Z_long Dy, /* I */ Z_long Dm); /* I */ boolean DateCalc_add_delta_ymd (Z_int *year, /* I/O */ Z_int *month, /* I/O */ Z_int *day, /* I/O */ Z_long Dy, /* I */ Z_long Dm, /* I */ Z_long Dd); /* I */ boolean DateCalc_add_delta_ymdhms (Z_int *year, /* I/O */ Z_int *month, /* I/O */ Z_int *day, /* I/O */ Z_int *hour, /* I/O */ Z_int *min, /* I/O */ Z_int *sec, /* I/O */ Z_long D_y, /* I */ Z_long D_m, /* I */ Z_long D_d, /* I */ Z_long Dh, /* I */ Z_long Dm, /* I */ Z_long Ds); /* I */ boolean DateCalc_add_norm_delta_ymd (Z_int *year, /* I/O */ Z_int *month, /* I/O */ Z_int *day, /* I/O */ Z_long Dy, /* I */ Z_long Dm, /* I */ Z_long Dd); /* I */ boolean DateCalc_add_norm_delta_ymdhms (Z_int *year, /* I/O */ Z_int *month, /* I/O */ Z_int *day, /* I/O */ Z_int *hour, /* I/O */ Z_int *min, /* I/O */ Z_int *sec, /* I/O */ Z_long D_y, /* I */ Z_long D_m, /* I */ Z_long D_d, /* I */ Z_long Dh, /* I */ Z_long Dm, /* I */ Z_long Ds); /* I */ boolean DateCalc_system_clock (Z_int *year, /* O */ Z_int *month, /* O */ Z_int *day, /* O */ Z_int *hour, /* O */ Z_int *min, /* O */ Z_int *sec, /* O */ Z_int *doy, /* O */ Z_int *dow, /* O */ Z_int *dst, /* O */ boolean gmt); /* I */ boolean DateCalc_gmtime (Z_int *year, /* O */ Z_int *month, /* O */ Z_int *day, /* O */ Z_int *hour, /* O */ Z_int *min, /* O */ Z_int *sec, /* O */ Z_int *doy, /* O */ Z_int *dow, /* O */ Z_int *dst, /* O */ time_t seconds); /* I */ boolean DateCalc_localtime (Z_int *year, /* O */ Z_int *month, /* O */ Z_int *day, /* O */ Z_int *hour, /* O */ Z_int *min, /* O */ Z_int *sec, /* O */ Z_int *doy, /* O */ Z_int *dow, /* O */ Z_int *dst, /* O */ time_t seconds); /* I */ boolean DateCalc_mktime (time_t *seconds, /* O */ Z_int year, /* I */ Z_int month, /* I */ Z_int day, /* I */ Z_int hour, /* I */ Z_int min, /* I */ Z_int sec, /* I */ Z_int doy, /* I */ Z_int dow, /* I */ Z_int dst); /* I */ boolean DateCalc_timezone (Z_int *year, /* O */ Z_int *month, /* O */ Z_int *day, /* O */ Z_int *hour, /* O */ Z_int *min, /* O */ Z_int *sec, /* O */ Z_int *dst, /* O */ time_t when); /* I */ boolean DateCalc_date2time (time_t *seconds, /* O */ Z_int year, /* I */ Z_int month, /* I */ Z_int day, /* I */ Z_int hour, /* I */ Z_int min, /* I */ Z_int sec); /* I */ boolean DateCalc_time2date (Z_int *year, /* O */ Z_int *month, /* O */ Z_int *day, /* O */ Z_int *hour, /* O */ Z_int *min, /* O */ Z_int *sec, /* O */ time_t seconds); /* I */ boolean DateCalc_easter_sunday (Z_int *year, /* I/O */ Z_int *month, /* O */ Z_int *day); /* O */ Z_int DateCalc_Decode_Month (charptr buffer, Z_int length, Z_int lang); Z_int DateCalc_Decode_Day_of_Week (charptr buffer, Z_int length, Z_int lang); Z_int DateCalc_Decode_Language (charptr buffer, Z_int length); boolean DateCalc_decode_date_eu (charptr buffer, /* I */ Z_int *year, /* O */ Z_int *month, /* O */ Z_int *day, /* O */ Z_int lang); /* I */ boolean DateCalc_decode_date_us (charptr buffer, /* I */ Z_int *year, /* O */ Z_int *month, /* O */ Z_int *day, /* O */ Z_int lang); /* I */ Z_int DateCalc_Fixed_Window (Z_int year); Z_int DateCalc_Moving_Window (Z_int year); Z_int DateCalc_Compress (Z_int year, Z_int month, Z_int day); boolean DateCalc_uncompress (Z_int date, /* I */ Z_int *century, /* O */ Z_int *year, /* O */ Z_int *month, /* O */ Z_int *day); /* O */ boolean DateCalc_check_compressed (Z_int date); charptr DateCalc_Compressed_to_Text (Z_int date, Z_int lang); charptr DateCalc_Date_to_Text (Z_int year, Z_int month, Z_int day, Z_int lang); charptr DateCalc_Date_to_Text_Long (Z_int year, Z_int month, Z_int day, Z_int lang); charptr /* O */ DateCalc_English_Ordinal (charptr result, /* O */ Z_int number); /* I */ charptr DateCalc_Calendar (Z_int year, Z_int month, boolean orthodox, Z_int lang); void DateCalc_Dispose (charptr string); N_char DateCalc_ISO_LC (N_char c); N_char DateCalc_ISO_UC (N_char c); charptr DateCalc_Version (void); /*****************************************************************************/ /* MODULE RESOURCES: */ /*****************************************************************************/ #define DateCalc_YEAR_OF_EPOCH 70 /* year of reference (epoch) */ #define DateCalc_CENTURY_OF_EPOCH 1900 /* century of reference (epoch) */ #define DateCalc_EPOCH (DateCalc_CENTURY_OF_EPOCH + DateCalc_YEAR_OF_EPOCH) const Z_int DateCalc_Days_in_Year_[2][14] = { { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } }; const Z_int DateCalc_Days_in_Month_[2][13] = { { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; #define DateCalc_LANGUAGES 14 Z_int DateCalc_Language = 1; /* Default = 1 (English) */ const N_char DateCalc_Month_to_Text_[DateCalc_LANGUAGES+1][13][32] = { { "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???" }, { "???", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }, { "???", "janvier", "février", "mars", "avril", "mai", "juin", "juillet", "aoűt", "septembre", "octobre", "novembre", "décembre" }, { "???", "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember" }, { "???", "enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre" }, { "???", "janeiro", "fevereiro", "março", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro" }, { "???", "januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december" }, { "???", "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" }, { "???", "januar", "februar", "mars", "april", "mai", "juni", "juli", "august", "september", "oktober", "november", "desember" }, { "???", "januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december" }, { "???", "januar", "februar", "marts", "april", "maj", "juni", "juli", "august", "september", "oktober", "november", "december" }, { "???", "tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu" }, { "???", "Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December" }, { "???", "Styczen", "Luty", "Marzec", "Kwiecien", "Maj", "Czerwiec", /* ISO-Latin-1 approximation */ "Lipiec", "Sierpien", "Wrzesien", "Pazdziernik", "Listopad", "Grudzien" }, { "???", "Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie" } }; const N_char DateCalc_Day_of_Week_to_Text_[DateCalc_LANGUAGES+1][8][32] = { { "???", "???", "???", "???", "???", "???", "???", "???" }, { "???", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }, { "???", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche" }, { "???", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag" }, { "???", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo" }, { "???", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado", "Domingo" }, { "???", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag" }, { "???", "Lunedě", "Martedě", "Mercoledě", "Giovedě", "Venerdě", "Sabato", "Domenica" }, { "???", "mandag", "tirsdag", "onsdag", "torsdag", "fredag", "lřrdag", "sřndag" }, { "???", "mĺndag", "tisdag", "onsdag", "torsdag", "fredag", "lördag", "söndag" }, { "???", "mandag", "tirsdag", "onsdag", "torsdag", "fredag", "lřrdag", "sřndag" }, { "???", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai" }, { "???", "hétfő", "kedd", "szerda", "csütörtök", "péntek", "szombat", "vasárnap" }, { "???", "poniedzialek", "wtorek", "sroda", /* ISO-Latin-1 approximation */ "czwartek", "piatek", "sobota", "niedziela" }, { "???", "Luni", "Marti", "Miercuri", "Joi", "Vineri", "Sambata", "Duminica" } }; const N_char DateCalc_Day_of_Week_Abbreviation_[DateCalc_LANGUAGES+1][8][4] = /* Fill the fields below _only_ if special abbreviations are needed! */ /* Note that the first field serves as a flag and must be non-empty! */ { { "", "", "", "", "", "", "", "" /* 0 */ }, { "", "", "", "", "", "", "", "" /* 1 */ }, { "", "", "", "", "", "", "", "" /* 2 */ }, { "", "", "", "", "", "", "", "" /* 3 */ }, { "", "", "", "", "", "", "", "" /* 4 */ }, { "", "", "", "", "", "", "", "" /* 5 */ /* "???", "2Ş", "3Ş", "4Ş", "5Ş", "6Ş", "Sáb", "Dom" /* 5 */ }, { "", "", "", "", "", "", "", "" /* 6 */ }, { "", "", "", "", "", "", "", "" /* 7 */ }, { "", "", "", "", "", "", "", "" /* 8 */ }, { "", "", "", "", "", "", "", "" /* 9 */ }, { "", "", "", "", "", "", "", "" /* 10 */ }, { "", "", "", "", "", "", "", "" /* 11 */ }, { "", "", "", "", "", "", "", "" /* 12 */ }, { "???", "Pn", "Wt", "Sr", "Cz", "Pt", "So", "Ni" /* 13 */ /* ISO-Latin-1 approximation */ }, { "", "", "", "", "", "", "", "" /* 14 */ } }; const N_char DateCalc_English_Ordinals_[4][4] = { "th", "st", "nd", "rd" }; const N_char DateCalc_Date_Long_Format_[DateCalc_LANGUAGES+1][64] = { "%s, %d %s %d", /* 0 Default */ "%s, %s %s %d", /* 1 English */ "%s %d %s %d", /* 2 Français */ "%s, den %d. %s %d", /* 3 Deutsch */ "%s, %d de %s de %d", /* 4 Espańol */ "%s, dia %d de %s de %d", /* 5 Portuguęs */ "%s, %d %s %d", /* 6 Nederlands */ "%s, %d %s %d", /* 7 Italiano */ "%s, %d. %s %d", /* 8 Norsk */ "%s, %d %s %d", /* 9 Svenska */ "%s, %d. %s %d", /* 10 Dansk */ "%s, %d. %sta %d", /* 11 suomi */ "%d. %s %d., %s", /* 12 Magyar */ "%s, %d %s %d", /* 13 polski */ "%s %d %s %d" /* 14 Romaneste */ }; const N_char DateCalc_Language_to_Text_[DateCalc_LANGUAGES+1][32] = { "???", "English", "Français", "Deutsch", "Espańol", "Portuguęs", "Nederlands", "Italiano", "Norsk", "Svenska", "Dansk", "suomi", "Magyar", "polski", "Romaneste" }; /*****************************************************************************/ /* MODULE IMPLEMENTATION: */ /*****************************************************************************/ static boolean DateCalc_is_digit(N_char c) { N_int i = (N_int) c; if ((i >= 0x30) and (i <= 0x39)) return(true); return(false); } static boolean DateCalc_is_alnum(N_char c) { N_int i = (N_int) c; if (((i >= 0x30) and (i <= 0x39)) or ((i >= 0x41) and (i <= 0x5A)) or ((i >= 0x61) and (i <= 0x7A)) or ((i >= 0xC0) and (i <= 0xD6)) or ((i >= 0xD8) and (i <= 0xF6)) or ((i >= 0xF8) and (i <= 0xFF))) return(true); return(false); } N_char DateCalc_ISO_LC(N_char c) { N_int i = (N_int) c; if (((i >= 0x41) and (i <= 0x5A)) or ((i >= 0xC0) and (i <= 0xD6)) or ((i >= 0xD8) and (c <= 0xDE))) i += 0x20; return((N_char) i); } N_char DateCalc_ISO_UC(N_char c) { N_int i = (N_int) c; if (((i >= 0x61) and (i <= 0x7A)) or ((i >= 0xE0) and (i <= 0xF6)) or ((i >= 0xF8) and (c <= 0xFE))) i -= 0x20; return((N_char) i); } static Z_long DateCalc_Year_to_Days(Z_int year) { Z_long days; days = year * 365L; days += year >>= 2; days -= year /= 25; days += year >> 2; return(days); } static boolean DateCalc_scan9(charptr str, Z_int len, Z_int idx, boolean neg) { /* Mnemonic: COBOL "PIC 9" */ if ((str != NULL) and (idx >= 0) and (idx < len)) return( DateCalc_is_digit(str[idx]) XOR neg ); return(false); } static boolean DateCalc_scanx(charptr str, Z_int len, Z_int idx, boolean neg) { /* Mnemonic: COBOL "PIC X" */ if ((str != NULL) and (idx >= 0) and (idx < len)) return( DateCalc_is_alnum(str[idx]) XOR neg ); return(false); } static Z_int DateCalc_Str2Int(charptr string, Z_int length) { Z_int number = 0; while (length-- > 0) { if (number) number *= 10; number += (Z_int) (*string++ - '0'); } return(number); } static void DateCalc_Center(charptr *target, charptr source, Z_int width) { Z_int length; Z_int blank; length = strlen((char *)source); if (length > width) length = width; blank = width - length; blank >>= 1; while (blank-- > 0) *(*target)++ = ' '; while (length-- > 0) *(*target)++ = *source++; *(*target)++ = '\n'; *(*target) = '\0'; } static void DateCalc_Blank(charptr *target, Z_int count) { while (count-- > 0) *(*target)++ = ' '; *(*target) = '\0'; } static void DateCalc_Newline(charptr *target, Z_int count) { while (count-- > 0) *(*target)++ = '\n'; *(*target) = '\0'; } static void DateCalc_Normalize_Time(Z_long *Dd, Z_long *Dh, Z_long *Dm, Z_long *Ds) { Z_long quot; quot = (Z_long) (*Ds / 60L); *Ds -= quot * 60L; *Dm += quot; quot = (Z_long) (*Dm / 60L); *Dm -= quot * 60L; *Dh += quot; quot = (Z_long) (*Dh / 24L); *Dh -= quot * 24L; *Dd += quot; } static void DateCalc_Normalize_Ranges(Z_long *Dd, Z_long *Dh, Z_long *Dm, Z_long *Ds) { Z_long quot; /* Prevent overflow errors on systems */ /* with short "long"s (e.g. 32 bits): */ quot = (Z_long) (*Dh / 24L); *Dh -= quot * 24L; *Dd += quot; quot = (Z_long) (*Dm / 60L); *Dm -= quot * 60L; *Dh += quot; DateCalc_Normalize_Time(Dd,Dh,Dm,Ds); } static void DateCalc_Normalize_Signs(Z_long *Dd, Z_long *Dh, Z_long *Dm, Z_long *Ds) { Z_long quot; quot = (Z_long) (*Ds / 86400L); *Ds -= quot * 86400L; *Dd += quot; if (*Dd != 0L) { if (*Dd > 0L) { if (*Ds < 0L) { *Ds += 86400L; (*Dd)--; } } else { if (*Ds > 0L) { *Ds -= 86400L; (*Dd)++; } } } *Dh = 0L; *Dm = 0L; if (*Ds != 0L) DateCalc_Normalize_Time(Dd,Dh,Dm,Ds); } void DateCalc_Normalize_DHMS(Z_long *Dd, Z_long *Dh, Z_long *Dm, Z_long *Ds) { DateCalc_Normalize_Ranges(Dd,Dh,Dm,Ds); *Ds += ((*Dh * 60L) + *Dm) * 60L; DateCalc_Normalize_Signs(Dd,Dh,Dm,Ds); } /*****************************************************************************/ boolean DateCalc_leap_year(Z_int year) { Z_int yy; return( ((year AND 0x03) == 0) and ( (((yy = (Z_int) (year / 100)) * 100) != year) or ((yy AND 0x03) == 0) ) ); } boolean DateCalc_check_date(Z_int year, Z_int month, Z_int day) { if ((year >= 1) and (month >= 1) and (month <= 12) and (day >= 1) and (day <= DateCalc_Days_in_Month_[DateCalc_leap_year(year)][month])) return(true); return(false); } boolean DateCalc_check_time(Z_int hour, Z_int min, Z_int sec) { if ((hour >= 0) and (min >= 0) and (sec >= 0) and (hour < 24) and (min < 60) and (sec < 60)) return(true); return(false); } boolean DateCalc_check_business_date(Z_int year, Z_int week, Z_int dow) { if ((year >= 1) and (week >= 1) and (week <= DateCalc_Weeks_in_Year(year)) and (dow >= 1) and (dow <= 7)) return(true); return(false); } Z_int DateCalc_Day_of_Year(Z_int year, Z_int month, Z_int day) { boolean leap; if ((year >= 1) and (month >= 1) and (month <= 12) and (day >= 1) and (day <= DateCalc_Days_in_Month_[leap=DateCalc_leap_year(year)][month])) return( DateCalc_Days_in_Year_[leap][month] + day ); return(0); } Z_long DateCalc_Date_to_Days(Z_int year, Z_int month, Z_int day) { boolean leap; if ((year >= 1) and (month >= 1) and (month <= 12) and (day >= 1) and (day <= DateCalc_Days_in_Month_[leap=DateCalc_leap_year(year)][month])) return( DateCalc_Year_to_Days(--year) + DateCalc_Days_in_Year_[leap][month] + day ); return(0L); } Z_int DateCalc_Day_of_Week(Z_int year, Z_int month, Z_int day) { Z_long days; days = DateCalc_Date_to_Days(year,month,day); if (days > 0L) { days--; days %= 7L; days++; } return( (Z_int) days ); } Z_int DateCalc_Weeks_in_Year(Z_int year) { return( 52 + ((DateCalc_Day_of_Week(year,1,1) == 4) or (DateCalc_Day_of_Week(year,12,31) == 4)) ); } Z_int DateCalc_Week_Number(Z_int year, Z_int month, Z_int day) { Z_int first; first = DateCalc_Day_of_Week(year,1,1) - 1; return( (Z_int) ( (DateCalc_Delta_Days(year,1,1, year,month,day) + first) / 7L ) + (first < 4) ); } boolean DateCalc_week_of_year(Z_int *week, Z_int *year, Z_int month, Z_int day) { if (DateCalc_check_date(*year,month,day)) { *week = DateCalc_Week_Number(*year,month,day); if (*week == 0) *week = DateCalc_Weeks_in_Year(--(*year)); else if (*week > DateCalc_Weeks_in_Year(*year)) { *week = 1; (*year)++; } return(true); } return(false); } boolean DateCalc_monday_of_week(Z_int week, Z_int *year, Z_int *month, Z_int *day) { Z_int first; *month = *day = 1; first = DateCalc_Day_of_Week(*year,1,1) - 1; if (first < 4) week--; return( DateCalc_add_delta_days(year,month,day, (week * 7L - first)) ); } boolean DateCalc_nth_weekday_of_month_year(Z_int *year, Z_int *month, Z_int *day, Z_int dow, Z_int n) { Z_int mm = *month; Z_int first; Z_long delta; *day = 1; if ((*year < 1) or (mm < 1) or (mm > 12) or (dow < 1) or (dow > 7) or (n < 1) or (n > 5)) return(false); first = DateCalc_Day_of_Week(*year,mm,1); if (dow < first) dow += 7; delta = (Z_long) (dow - first); delta += (n-1) * 7L; if (DateCalc_add_delta_days(year,month,day,delta) and (*month == mm)) return(true); return(false); } boolean DateCalc_standard_to_business(Z_int *year, Z_int *week, Z_int *dow, Z_int month, Z_int day) { Z_int yy = *year; if (DateCalc_week_of_year(week,year,month,day)) { *dow = DateCalc_Day_of_Week(yy,month,day); return(true); } return(false); } boolean DateCalc_business_to_standard(Z_int *year, Z_int *month, Z_int *day, Z_int week, Z_int dow) { Z_int first; Z_long delta; if (DateCalc_check_business_date(*year,week,dow)) { *month = *day = 1; first = DateCalc_Day_of_Week(*year,1,1); delta = ((week + (first > 4) - 1) * 7L) + (dow - first); return( DateCalc_add_delta_days(year,month,day,delta) ); } return(false); } Z_long DateCalc_Delta_Days(Z_int year1, Z_int month1, Z_int day1, Z_int year2, Z_int month2, Z_int day2) { return( DateCalc_Date_to_Days(year2,month2,day2) - DateCalc_Date_to_Days(year1,month1,day1) ); } boolean 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) { Z_long HH; Z_long MM; Z_long SS; if (DateCalc_check_time(hour1,min1,sec1) and DateCalc_check_time(hour2,min2,sec2)) { SS = ((((hour2 * 60L) + min2) * 60L) + sec2) - ((((hour1 * 60L) + min1) * 60L) + sec1); DateCalc_Normalize_Signs(Dd,&HH,&MM,&SS); *Dh = (Z_int) HH; *Dm = (Z_int) MM; *Ds = (Z_int) SS; return(true); } return(false); } boolean 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) { *Dd = *Dh = *Dm = *Ds = 0; if (DateCalc_check_date(year1,month1,day1) and DateCalc_check_date(year2,month2,day2)) { *Dd = DateCalc_Delta_Days(year1,month1,day1, year2,month2,day2); return( DateCalc_delta_hms(Dd,Dh,Dm,Ds, hour1,min1,sec1, hour2,min2,sec2) ); } return(false); } boolean DateCalc_delta_ymd(Z_int *year1, Z_int *month1, Z_int *day1, Z_int year2, Z_int month2, Z_int day2) { if (DateCalc_check_date(*year1,*month1,*day1) and DateCalc_check_date(year2,month2,day2)) { *day1 = day2 - *day1; *month1 = month2 - *month1; *year1 = year2 - *year1; return(true); } return(false); } boolean 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) { Z_long Dd; if (not DateCalc_delta_ymd(&year1,&month1,&day1, year2,month2,day2)) return(false); Dd = (Z_long) day1; if (not DateCalc_delta_hms(&Dd,Dh,Dm,Ds, hour1,min1,sec1, hour2,min2,sec2)) return(false); *D_y = year1; *D_m = month1; *D_d = (Z_int) Dd; return(true); } boolean DateCalc_norm_delta_ymd(Z_int *year1, Z_int *month1, Z_int *day1, Z_int year2, Z_int month2, Z_int day2) { Z_long Dy = 0L; Z_long Dm = 0L; Z_long Dd = 0L; Z_long d2; Z_int ty; Z_int tm; Z_int td; if (DateCalc_check_date(*year1,*month1,*day1) and DateCalc_check_date(year2,month2,day2)) { d2 = DateCalc_Date_to_Days(year2,month2,day2); Dd = d2-DateCalc_Date_to_Days(*year1,*month1,*day1); if ((Dd < -30L) or (Dd > 30L)) { Dy = (Z_long) (year2 - *year1); Dm = (Z_long) (month2 - *month1); 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); if (!(((Dy >= 0L) and (Dm >= 0L) and (Dd >= 0L)) or ((Dy <= 0L) and (Dm <= 0L) and (Dd <= 0L)))) { if ((Dy < 0L) and (Dm > 0L)) { Dy++; Dm -= 12L; } else if ((Dy > 0L) and (Dm < 0L)) { Dy--; Dm += 12L; } 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); } 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); } if ((Dy < 0L) and (Dd > 0L)) { Dy++; Dm -= 12L; } else if ((Dy > 0L) and (Dd < 0L)) { Dy--; Dm += 12L; } 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); } 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); } } } *year1 = (Z_int) Dy; *month1 = (Z_int) Dm; *day1 = (Z_int) Dd; return(true); } return(false); } boolean 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) { Z_long Dy = 0L; Z_long Dm = 0L; Z_long Dd = 0L; Z_long d2, hh, mm, ss; Z_int ty; Z_int tm; Z_int td; if (DateCalc_check_date(year1,month1,day1) and DateCalc_check_time(hour1,min1, sec1) and DateCalc_check_date(year2,month2,day2) and DateCalc_check_time(hour1,min2, sec2)) { ss = ( (hour2-hour1) * 60L + (min2-min1) ) * 60L + (sec2-sec1); d2 = DateCalc_Date_to_Days(year2,month2,day2); Dd = d2-DateCalc_Date_to_Days(year1,month1,day1); if ((Dd < -30L) or (Dd > 30L)) { Dy = (Z_long) (year2 - year1); Dm = (Z_long) (month2 - month1); 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); if (!(((Dy >= 0L) and (Dm >= 0L) and (Dd >= 0L) and (ss >= 0L)) or ((Dy <= 0L) and (Dm <= 0L) and (Dd <= 0L) and (ss <= 0L)))) { if ((Dy < 0L) and (Dm > 0L)) { Dy++; Dm -= 12L; } else if ((Dy > 0L) and (Dm < 0L)) { Dy--; Dm += 12L; } 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); } 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); } if ((Dy < 0L) and (Dd > 0L)) { Dy++; Dm -= 12L; } else if ((Dy > 0L) and (Dd < 0L)) { Dy--; Dm += 12L; } 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); } 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); } if ((Dd < 0L) and (ss > 0L)) { Dd++; ss -= 86400L; } else if ((Dd > 0L) and (ss < 0L)) { Dd--; ss += 86400L; } 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); } 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); } if ((Dy < 0L) and (ss > 0L)) { Dy++; Dm -= 12L; } else if ((Dy > 0L) and (ss < 0L)) { Dy--; Dm += 12L; } 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); } 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); } if ((Dd < 0L) and (ss > 0L)) { Dd++; ss -= 86400L; } else if ((Dd > 0L) and (ss < 0L)) { Dd--; ss += 86400L; } } } else { if ((Dd < 0L) and (ss > 0L)) { Dd++; ss -= 86400L; } else if ((Dd > 0L) and (ss < 0L)) { Dd--; ss += 86400L; } } mm = (Z_long) ( ss / 60 ); ss -= mm * 60; hh = (Z_long) ( mm / 60 ); mm -= hh * 60; *D_y = (Z_int) Dy; *D_m = (Z_int) Dm; *D_d = (Z_int) Dd; *Dhh = (Z_int) hh; *Dmm = (Z_int) mm; *Dss = (Z_int) ss; return(true); } return(false); } boolean DateCalc_add_delta_days(Z_int *year, Z_int *month, Z_int *day, Z_long Dd) { Z_long days; boolean leap; if (((days = DateCalc_Date_to_Days(*year,*month,*day)) > 0L) and ((days += Dd) > 0L)) { if (Dd != 0L) { *year = (Z_int) ( days / 365.2425 ); *day = (Z_int) ( days - DateCalc_Year_to_Days(*year) ); if (*day < 1) { *day = (Z_int) ( days - DateCalc_Year_to_Days(*year-1) ); } else (*year)++; leap = DateCalc_leap_year(*year); if (*day > DateCalc_Days_in_Year_[leap][13]) { *day -= DateCalc_Days_in_Year_[leap][13]; leap = DateCalc_leap_year(++(*year)); } for ( *month = 12; *month >= 1; (*month)-- ) { if (*day > DateCalc_Days_in_Year_[leap][*month]) { *day -= DateCalc_Days_in_Year_[leap][*month]; break; } } } return(true); } return(false); } boolean 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) { if (DateCalc_check_date(*year,*month,*day) and DateCalc_check_time(*hour,*min,*sec)) { DateCalc_Normalize_Ranges(&Dd,&Dh,&Dm,&Ds); Ds += ((((*hour * 60L) + *min) * 60L) + *sec) + ((( Dh * 60L) + Dm) * 60L); while (Ds < 0L) { Ds += 86400L; Dd--; } if (Ds > 0L) { Dh = 0L; Dm = 0L; DateCalc_Normalize_Time(&Dd,&Dh,&Dm,&Ds); *hour = (Z_int) Dh; *min = (Z_int) Dm; *sec = (Z_int) Ds; } else *hour = *min = *sec = 0; return( DateCalc_add_delta_days(year,month,day,Dd) ); } return(false); } boolean DateCalc_add_year_month(Z_int *year, Z_int *month, Z_long Dy, Z_long Dm) { Z_long quot; if ((*year < 1) or (*month < 1) or (*month > 12)) return(false); if (Dm != 0L) { Dm += (Z_long) (*month - 1); quot = (Z_long) (Dm / 12L); Dm -= quot * 12L; if (Dm < 0L) { Dm += 12L; quot--; } *month = (Z_int) (Dm + 1); Dy += quot; } if (Dy != 0L) { Dy += (Z_long) *year; *year = (Z_int) Dy; } if (*year < 1) return(false); return(true); } boolean DateCalc_add_delta_ym(Z_int *year, Z_int *month, Z_int *day, Z_long Dy, Z_long Dm) { Z_int Dd; if (not DateCalc_check_date(*year,*month,*day)) return(false); if (not DateCalc_add_year_month(year,month,Dy,Dm)) return(false); if (*day > (Dd = DateCalc_Days_in_Month_[DateCalc_leap_year(*year)][*month])) *day = Dd; return(true); } boolean DateCalc_add_delta_ymd(Z_int *year, Z_int *month, Z_int *day, Z_long Dy, Z_long Dm, Z_long Dd) { if (not DateCalc_check_date(*year,*month,*day)) return(false); if (not DateCalc_add_year_month(year,month,Dy,Dm)) return(false); Dd += (Z_long) (*day - 1); *day = 1; return( DateCalc_add_delta_days(year,month,day,Dd) ); } boolean 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) { if (not (DateCalc_check_date(*year,*month,*day) and DateCalc_check_time(*hour,*min,*sec))) return(false); if (not DateCalc_add_year_month(year,month,D_y,D_m)) return(false); D_d += (Z_long) (*day - 1); *day = 1; return( DateCalc_add_delta_dhms(year,month,day,hour,min,sec,D_d,Dh,Dm,Ds) ); } boolean DateCalc_add_norm_delta_ymd(Z_int *year, Z_int *month, Z_int *day, Z_long Dy, Z_long Dm, Z_long Dd) { if (not DateCalc_add_delta_ym(year,month,day,Dy,Dm)) return(false); return( DateCalc_add_delta_days(year,month,day,Dd) ); } boolean 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) { if (not DateCalc_add_delta_ym(year,month,day,D_y,D_m)) return(false); return( DateCalc_add_delta_dhms(year,month,day,hour,min,sec,D_d,Dh,Dm,Ds) ); } boolean 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) { time_t seconds; struct tm *date; if (time(&seconds) >= 0) { if (gmt) date = gmtime(&seconds); else date = localtime(&seconds); if (date != NULL) { *year = (*date).tm_year + 1900; *month = (*date).tm_mon + 1; *day = (*date).tm_mday; *hour = (*date).tm_hour; *min = (*date).tm_min; *sec = (*date).tm_sec; *doy = (*date).tm_yday + 1; *dow = (*date).tm_wday; if (*dow == 0) *dow = 7; *dst = (*date).tm_isdst; if (*dst != 0) { if (*dst < 0) *dst = -1; else *dst = 1; } return(true); } } return(false); } boolean 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) { struct tm *date; if ((seconds >= 0) and ((date = gmtime(&seconds)) != NULL)) { *year = (*date).tm_year + 1900; *month = (*date).tm_mon + 1; *day = (*date).tm_mday; *hour = (*date).tm_hour; *min = (*date).tm_min; *sec = (*date).tm_sec; *doy = (*date).tm_yday + 1; *dow = (*date).tm_wday; if (*dow == 0) *dow = 7; *dst = (*date).tm_isdst; if (*dst != 0) { if (*dst < 0) *dst = -1; else *dst = 1; } return(true); } return(false); } boolean 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) { struct tm *date; if ((seconds >= 0) and ((date = localtime(&seconds)) != NULL)) { *year = (*date).tm_year + 1900; *month = (*date).tm_mon + 1; *day = (*date).tm_mday; *hour = (*date).tm_hour; *min = (*date).tm_min; *sec = (*date).tm_sec; *doy = (*date).tm_yday + 1; *dow = (*date).tm_wday; if (*dow == 0) *dow = 7; *dst = (*date).tm_isdst; if (*dst != 0) { if (*dst < 0) *dst = -1; else *dst = 1; } return(true); } return(false); } /* MacOS (Classic): */ /* <695056.0> = Fri 1-Jan-1904 00:00:00 (time=0x00000000) */ /* <744766.23295> = Mon 6-Feb-2040 06:28:15 (time=0xFFFFFFFF) */ /* Unix: */ /* <719163.0> = Thu 1-Jan-1970 00:00:00 (time=0x00000000) */ /* <744018.11647> = Tue 19-Jan-2038 03:14:07 (time=0x7FFFFFFF) */ boolean 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) { struct tm date; *seconds = (time_t) 0; #ifdef MACOS_TRADITIONAL if ( (year < 1904) or (year > 2040) or #else if ( (year < 1970) or (year > 2038) or #endif (month < 1) or (month > 12) or (day < 1) or (day > 31) or (hour < 0) or (hour > 23) or (min < 0) or (min > 59) or (sec < 0) or (sec > 59) ) return(false); #ifdef MACOS_TRADITIONAL if ( (year == 2040) and ( (month > 2) or ( (month == 2) and ( (day > 6) or ( (day == 6) and ( (hour > 6) or ( (hour == 6) and ( (min > 28) or ( (min == 28) and (sec > 15) ) ))))))) ) return(false); #else if ( (year == 2038) and ( (month > 1) or ( (month == 1) and ( (day > 19) or ( (day == 19) and ( (hour > 3) or ( (hour == 3) and ( (min > 14) or ( (min == 14) and (sec > 7) ) ))))))) ) return(false); #endif year -= 1900; month--; if (doy <= 0) doy = -1; else doy--; if (dow <= 0) dow = -1; else if (dow == 7) dow = 0; if (dst != 0) { if (dst < 0) dst = -1; else dst = 1; } date.tm_year = year; date.tm_mon = month; date.tm_mday = day; date.tm_hour = hour; date.tm_min = min; date.tm_sec = sec; date.tm_yday = doy; date.tm_wday = dow; date.tm_isdst = dst; *seconds = mktime(&date); return(*seconds >= 0); } boolean 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) { struct tm *date; 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; if (when >= 0) { if ((date = gmtime(&when)) == NULL) return(false); year1 = (*date).tm_year + 1900; month1 = (*date).tm_mon + 1; day1 = (*date).tm_mday; hour1 = (*date).tm_hour; min1 = (*date).tm_min; sec1 = (*date).tm_sec; if ((date = localtime(&when)) == NULL) return(false); year2 = (*date).tm_year + 1900; month2 = (*date).tm_mon + 1; day2 = (*date).tm_mday; hour2 = (*date).tm_hour; min2 = (*date).tm_min; sec2 = (*date).tm_sec; if (DateCalc_delta_ymdhms(year, month, day, hour, min, sec, year1,month1,day1, hour1,min1,sec1, year2,month2,day2, hour2,min2,sec2)) { *dst = (*date).tm_isdst; if (*dst != 0) { if (*dst < 0) *dst = -1; else *dst = 1; } return(true); } } return(false); } /* MacOS (Classic): */ /* <695056.0> = Fri 1-Jan-1904 00:00:00 (time=0x00000000) */ /* <744766.23295> = Mon 6-Feb-2040 06:28:15 (time=0xFFFFFFFF) */ /* Unix: */ /* <719163.0> = Thu 1-Jan-1970 00:00:00 (time=0x00000000) */ /* <744018.11647> = Tue 19-Jan-2038 03:14:07 (time=0x7FFFFFFF) */ #ifdef MACOS_TRADITIONAL #define DateCalc_DAYS_TO_EPOCH 695056L #define DateCalc_DAYS_TO_OVFLW 744766L #define DateCalc_SECS_TO_OVFLW 23295L #else #define DateCalc_DAYS_TO_EPOCH 719163L #define DateCalc_DAYS_TO_OVFLW 744018L #define DateCalc_SECS_TO_OVFLW 11647L #endif /* Substitute for BSD's timegm(3) function: */ boolean DateCalc_date2time(time_t *seconds, Z_int year, Z_int month, Z_int day, Z_int hour, Z_int min, Z_int sec) { Z_long days; #ifdef MACOS_TRADITIONAL N_long secs; #else Z_long secs; #endif *seconds = (time_t) 0; days = DateCalc_Date_to_Days(year,month,day); secs = (((hour * 60L) + min) * 60L) + sec; if ( (days < DateCalc_DAYS_TO_EPOCH) or #ifndef MACOS_TRADITIONAL (secs < 0L) or #endif (days > DateCalc_DAYS_TO_OVFLW) or ( (days == DateCalc_DAYS_TO_OVFLW) and (secs > DateCalc_SECS_TO_OVFLW) ) ) return(false); *seconds = (time_t) (((days - DateCalc_DAYS_TO_EPOCH) * 86400L) + secs); return(true); } /* Substitute for POSIX's gmtime(3) function: */ boolean DateCalc_time2date(Z_int *year, Z_int *month, Z_int *day, Z_int *hour, Z_int *min, Z_int *sec, time_t seconds) { #ifdef MACOS_TRADITIONAL N_long ss = (N_long) seconds; N_long mm; N_long hh; N_long dd; dd = (N_long) (ss / 86400L); ss -= dd * 86400L; mm = (N_long) (ss / 60L); ss -= mm * 60L; hh = (N_long) (mm / 60L); #else Z_long ss = (Z_long) seconds; Z_long mm; Z_long hh; Z_long dd; if (ss < 0L) return(false); dd = (Z_long) (ss / 86400L); ss -= dd * 86400L; mm = (Z_long) (ss / 60L); ss -= mm * 60L; hh = (Z_long) (mm / 60L); #endif mm -= hh * 60L; dd += (DateCalc_DAYS_TO_EPOCH-1L); *sec = (Z_int) ss; *min = (Z_int) mm; *hour = (Z_int) hh; *day = (Z_int) 1; *month = (Z_int) 1; *year = (Z_int) 1; return( DateCalc_add_delta_days(year,month,day,dd) ); } boolean DateCalc_easter_sunday(Z_int *year, Z_int *month, Z_int *day) { /****************************************************************/ /* */ /* Gauss'sche Regel (Gaussian Rule) */ /* ================================ */ /* */ /* Quelle / Source: */ /* */ /* H. H. Voigt, "Abriss der Astronomie", Wissenschaftsverlag, */ /* Bibliographisches Institut, Seite 9. */ /* */ /****************************************************************/ Z_int a, b, c, d, e, m, n; if ((*year < 1583) or (*year > 2299)) return(false); if (*year < 1700) { m = 22; n = 2; } else if (*year < 1800) { m = 23; n = 3; } else if (*year < 1900) { m = 23; n = 4; } else if (*year < 2100) { m = 24; n = 5; } else if (*year < 2200) { m = 24; n = 6; } else { m = 25; n = 0; } a = *year % 19; b = *year % 4; c = *year % 7; d = (19 * a + m) % 30; e = (2 * b + 4 * c + 6 * d + n) % 7; *day = 22 + d + e; *month = 3; if (*day > 31) { *day -= 31; /* same as *day = d + e - 9; */ (*month)++; } if ((*day == 26) and (*month == 4)) *day = 19; if ((*day == 25) and (*month == 4) and (d == 28) and (e == 6) and (a > 10)) *day = 18; return(true); } /* Carnival Monday / Rosenmontag / Veille du Mardi Gras = easter sunday - 48 */ /* Mardi Gras / Karnevalsdienstag / Mardi Gras = easter sunday - 47 */ /* Ash Wednesday / Aschermittwoch / Mercredi des Cendres = easter sunday - 46 */ /* Palm Sunday / Palmsonntag / Dimanche des Rameaux = easter sunday - 7 */ /* Easter Friday / Karfreitag / Vendredi Saint = easter sunday - 2 */ /* Easter Saturday / Ostersamstag / Samedi de Paques = easter sunday - 1 */ /* Easter Monday / Ostermontag / Lundi de Paques = easter sunday + 1 */ /* Ascension of Christ / Christi Himmelfahrt / Ascension = easter sunday + 39 */ /* Whitsunday / Pfingstsonntag / Dimanche de Pentecote = easter sunday + 49 */ /* Whitmonday / Pfingstmontag / Lundi de Pentecote = easter sunday + 50 */ /* Feast of Corpus Christi / Fronleichnam / Fete-Dieu = easter sunday + 60 */ Z_int DateCalc_Decode_Month(charptr buffer, Z_int length, Z_int lang) /* 0 = error */ { Z_int i,j; Z_int month; boolean same; boolean ok; /*****************************************************************************/ /* BEWARE that the parameter "length" must always be set in such a way */ /* so that the string in "buffer[0]" up to "buffer[length-1]" does not */ /* contain any terminating null character '\0'. Otherwise this routine */ /* may read beyond allocated memory, probably resulting in an access */ /* violation and program abortion. This problem cannot arise, for example, */ /* if you use the library function "strlen" to determine the length */ /* "length" of the string in "buffer". */ /*****************************************************************************/ if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language; month = 0; ok = true; for ( i = 1; ok and (i <= 12); i++ ) { same = true; for ( j = 0; same and (j < length); j++ ) { same = ( DateCalc_ISO_UC(buffer[j]) == DateCalc_ISO_UC(DateCalc_Month_to_Text_[lang][i][j]) ); } if (same) { if (month > 0) ok = false; else month = i; } } if (ok) return(month); else return(0); } Z_int DateCalc_Decode_Day_of_Week(charptr buffer, Z_int length, Z_int lang) /* 0 = error */ { Z_int i,j; Z_int day; boolean same; boolean ok; /*****************************************************************************/ /* BEWARE that the parameter "length" must always be set in such a way */ /* so that the string in "buffer[0]" up to "buffer[length-1]" does not */ /* contain any terminating null character '\0'. Otherwise this routine */ /* may read beyond allocated memory, probably resulting in an access */ /* violation and program abortion. This problem cannot arise, for example, */ /* if you use the library function "strlen" to determine the length */ /* "length" of the string in "buffer". */ /*****************************************************************************/ if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language; day = 0; ok = true; for ( i = 1; ok and (i <= 7); i++ ) { same = true; for ( j = 0; same and (j < length); j++ ) { same = ( DateCalc_ISO_UC(buffer[j]) == DateCalc_ISO_UC(DateCalc_Day_of_Week_to_Text_[lang][i][j]) ); } if (same) { if (day > 0) ok = false; else day = i; } } if (ok) return(day); else return(0); } Z_int DateCalc_Decode_Language(charptr buffer, Z_int length) /* 0 = error */ { Z_int i,j; Z_int lang; boolean same; boolean ok; /*****************************************************************************/ /* BEWARE that the parameter "length" must always be set in such a way */ /* so that the string in "buffer[0]" up to "buffer[length-1]" does not */ /* contain any terminating null character '\0'. Otherwise this routine */ /* may read beyond allocated memory, probably resulting in an access */ /* violation and program abortion. This problem cannot arise, for example, */ /* if you use the library function "strlen" to determine the length */ /* "length" of the string in "buffer". */ /*****************************************************************************/ lang = 0; ok = true; for ( i = 1; ok and (i <= DateCalc_LANGUAGES); i++ ) { same = true; for ( j = 0; same and (j < length); j++ ) { same = ( DateCalc_ISO_UC(buffer[j]) == DateCalc_ISO_UC(DateCalc_Language_to_Text_[i][j]) ); } if (same) { if (lang > 0) ok = false; else lang = i; } } if (ok) return(lang); else return(0); } boolean DateCalc_decode_date_eu(charptr buffer, Z_int *year, Z_int *month, Z_int *day, Z_int lang) { Z_int i,j; Z_int length; if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language; *year = *month = *day = 0; length = strlen((char *)buffer); if (length > 0) { i = 0; while (DateCalc_scan9(buffer,length,i,true)) i++; j = length-1; while (DateCalc_scan9(buffer,length,j,true)) j--; if (i+1 < j) /* at least 3 chars, else error! */ { buffer += i; length = j-i+1; i = 1; while (DateCalc_scan9(buffer,length,i,false)) i++; j = length-2; while (DateCalc_scan9(buffer,length,j,false)) j--; if (j < i) /* only numerical chars without delimiters */ { switch (length) { case 3: *day = DateCalc_Str2Int(buffer, 1); *month = DateCalc_Str2Int(buffer+1,1); *year = DateCalc_Str2Int(buffer+2,1); break; case 4: *day = DateCalc_Str2Int(buffer, 1); *month = DateCalc_Str2Int(buffer+1,1); *year = DateCalc_Str2Int(buffer+2,2); break; case 5: *day = DateCalc_Str2Int(buffer, 1); *month = DateCalc_Str2Int(buffer+1,2); *year = DateCalc_Str2Int(buffer+3,2); break; case 6: *day = DateCalc_Str2Int(buffer, 2); *month = DateCalc_Str2Int(buffer+2,2); *year = DateCalc_Str2Int(buffer+4,2); break; case 7: *day = DateCalc_Str2Int(buffer, 1); *month = DateCalc_Str2Int(buffer+1,2); *year = DateCalc_Str2Int(buffer+3,4); break; case 8: *day = DateCalc_Str2Int(buffer, 2); *month = DateCalc_Str2Int(buffer+2,2); *year = DateCalc_Str2Int(buffer+4,4); break; default: return(false); break; } } else /* at least one non-numerical char (i <= j) */ { *day = DateCalc_Str2Int(buffer,i); *year = DateCalc_Str2Int(buffer+(j+1),length-(j+1)); while (DateCalc_scanx(buffer,length,i,true)) i++; while (DateCalc_scanx(buffer,length,j,true)) j--; if (i <= j) /* at least one char left for month */ { buffer += i; length = j-i+1; i = 1; while (DateCalc_scanx(buffer,length,i,false)) i++; if (i >= length) /* ok, no more delimiters */ { i = 0; while (DateCalc_scan9(buffer,length,i,false)) i++; if (i >= length) /* only digits for month */ { *month = DateCalc_Str2Int(buffer,length); } else /* match with month names */ { *month = DateCalc_Decode_Month(buffer,length,lang); } } else return(false); /* delimiters inside month string */ } else return(false); /* no chars left for month */ } /* at least one non-numerical char (i <= j) */ } else return(false); /* less than 3 chars in buffer */ } else return(false); /* length <= 0 */ *year = DateCalc_Moving_Window(*year); return( DateCalc_check_date(*year,*month,*day) ); } boolean DateCalc_decode_date_us(charptr buffer, Z_int *year, Z_int *month, Z_int *day, Z_int lang) { Z_int i,j,k; Z_int length; if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language; *year = *month = *day = 0; length = strlen((char *)buffer); if (length > 0) { i = 0; while (DateCalc_scanx(buffer,length,i,true)) i++; j = length-1; while (DateCalc_scan9(buffer,length,j,true)) j--; if (i+1 < j) /* at least 3 chars, else error! */ { buffer += i; length = j-i+1; i = 1; while (DateCalc_scanx(buffer,length,i,false)) i++; j = length-2; while (DateCalc_scan9(buffer,length,j,false)) j--; if (i >= length) /* only alphanumeric chars left */ { if (j < 0) /* case 0 : xxxx999999xxxx */ { /* j0 i */ switch (length) { case 3: *month = DateCalc_Str2Int(buffer, 1); *day = DateCalc_Str2Int(buffer+1,1); *year = DateCalc_Str2Int(buffer+2,1); break; case 4: *month = DateCalc_Str2Int(buffer, 1); *day = DateCalc_Str2Int(buffer+1,1); *year = DateCalc_Str2Int(buffer+2,2); break; case 5: *month = DateCalc_Str2Int(buffer, 1); *day = DateCalc_Str2Int(buffer+1,2); *year = DateCalc_Str2Int(buffer+3,2); break; case 6: *month = DateCalc_Str2Int(buffer, 2); *day = DateCalc_Str2Int(buffer+2,2); *year = DateCalc_Str2Int(buffer+4,2); break; case 7: *month = DateCalc_Str2Int(buffer, 1); *day = DateCalc_Str2Int(buffer+1,2); *year = DateCalc_Str2Int(buffer+3,4); break; case 8: *month = DateCalc_Str2Int(buffer, 2); *day = DateCalc_Str2Int(buffer+2,2); *year = DateCalc_Str2Int(buffer+4,4); break; default: return(false); break; } } else /* case 1 : xxxxAAA999999xxxx */ { /* 0 j i */ *month = DateCalc_Decode_Month(buffer,j+1,lang); buffer += j+1; length -= j+1; switch (length) { case 2: *day = DateCalc_Str2Int(buffer, 1); *year = DateCalc_Str2Int(buffer+1,1); break; case 3: *day = DateCalc_Str2Int(buffer, 1); *year = DateCalc_Str2Int(buffer+1,2); break; case 4: *day = DateCalc_Str2Int(buffer, 2); *year = DateCalc_Str2Int(buffer+2,2); break; case 5: *day = DateCalc_Str2Int(buffer, 1); *year = DateCalc_Str2Int(buffer+1,4); break; case 6: *day = DateCalc_Str2Int(buffer, 2); *year = DateCalc_Str2Int(buffer+2,4); break; default: return(false); break; } } } /* 0 i j l */ else /* case 2 : xxxxAAAxxxx9999xxxx _OR_ */ { /* case 3 : xxxxAAAxx99xx9999xx */ k = 0; /* 0 i j l */ while (DateCalc_scan9(buffer,length,k,false)) k++; if (k >= i) /* ok, only digits */ { *month = DateCalc_Str2Int(buffer,i); } else /* no, some non-digits */ { *month = DateCalc_Decode_Month(buffer,i,lang); if (*month == 0) return(false); } buffer += i; length -= i; j -= i; k = j+1; /* remember start posn of day+year(2)/year(3) */ i = 1; while (DateCalc_scanx(buffer,length,i,true)) i++; j--; while (DateCalc_scan9(buffer,length,j,true)) j--; if (j < i) /* case 2 : xxxxAAAxxxx9999xxxx */ { /* j0 i l */ buffer += k; /* k */ length -= k; switch (length) { case 2: *day = DateCalc_Str2Int(buffer, 1); *year = DateCalc_Str2Int(buffer+1,1); break; case 3: *day = DateCalc_Str2Int(buffer, 1); *year = DateCalc_Str2Int(buffer+1,2); break; case 4: *day = DateCalc_Str2Int(buffer, 2); *year = DateCalc_Str2Int(buffer+2,2); break; case 5: *day = DateCalc_Str2Int(buffer, 1); *year = DateCalc_Str2Int(buffer+1,4); break; case 6: *day = DateCalc_Str2Int(buffer, 2); *year = DateCalc_Str2Int(buffer+2,4); break; default: return(false); break; } } else /* case 3 : xxxxAAAxx99xx9999xx */ { /* 0 ij k l */ *year = DateCalc_Str2Int(buffer+k,length-k); k = i; while (DateCalc_scan9(buffer,length,k,false)) k++; if (k > j) /* ok, only digits */ { *day = DateCalc_Str2Int(buffer+i,j-i+1); } else return(false); /* non-digits inside day */ } } /* i < length */ } else return(false); /* less than 3 chars in buffer */ } else return(false); /* length <= 0 */ *year = DateCalc_Moving_Window(*year); return( DateCalc_check_date(*year,*month,*day) ); } Z_int DateCalc_Fixed_Window(Z_int year) { if (year < 0) return(0); if (year < 100) { if (year < DateCalc_YEAR_OF_EPOCH) year += 100; year += DateCalc_CENTURY_OF_EPOCH; } return(year); } Z_int DateCalc_Moving_Window(Z_int year) { time_t seconds; struct tm *date; Z_int current; Z_int century; if (year < 0) return(0); if (year < 100) { if ((time(&seconds) >= 0) and ((date = gmtime(&seconds)) != NULL)) { current = (*date).tm_year + 1900; century = (Z_int)(current / 100); year += century * 100; if (year < current - 50) year += 100; else if (year >= current + 50) year -= 100; } else year = DateCalc_Fixed_Window(year); } return(year); } Z_int DateCalc_Compress(Z_int year, Z_int month, Z_int day) { Z_int yy; if ((year >= DateCalc_EPOCH) and (year < (DateCalc_EPOCH + 100))) { yy = year; year -= DateCalc_EPOCH; } else { if ((year < 0) or (year > 99)) return(0); if (year < DateCalc_YEAR_OF_EPOCH) { yy = DateCalc_CENTURY_OF_EPOCH + 100 + year; year += 100 - DateCalc_YEAR_OF_EPOCH; } else { yy = DateCalc_CENTURY_OF_EPOCH + year; year -= DateCalc_YEAR_OF_EPOCH; } } if ((month < 1) or (month > 12)) return(0); if ((day < 1) or (day > DateCalc_Days_in_Month_[DateCalc_leap_year(yy)][month])) return(0); return( (year SHL 9) OR (month SHL 5) OR day ); } boolean DateCalc_uncompress(Z_int date, Z_int *century, Z_int *year, Z_int *month, Z_int *day) { if (date > 0) { *year = date SHR 9; *month = (date AND 0x01FF) SHR 5; *day = date AND 0x001F; if (*year < 100) { if (*year < 100-DateCalc_YEAR_OF_EPOCH) { *century = DateCalc_CENTURY_OF_EPOCH; *year += DateCalc_YEAR_OF_EPOCH; } else { *century = DateCalc_CENTURY_OF_EPOCH+100; *year -= 100-DateCalc_YEAR_OF_EPOCH; } return( DateCalc_check_date(*century+*year,*month,*day) ); } } return(false); } boolean DateCalc_check_compressed(Z_int date) { Z_int century; Z_int year; Z_int month; Z_int day; return( DateCalc_uncompress(date,¢ury,&year,&month,&day) ); } charptr DateCalc_Compressed_to_Text(Z_int date, Z_int lang) { Z_int century; Z_int year; Z_int month; Z_int day; charptr string; if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language; string = (charptr) malloc(16); if (string == NULL) return(NULL); if (DateCalc_uncompress(date,¢ury,&year,&month,&day)) sprintf((char *)string,"%02d-%.3s-%02d",day, DateCalc_Month_to_Text_[lang][month],year); else sprintf((char *)string,"??""-???""-??"); /* prevent interpretation as trigraphs */ return(string); } charptr DateCalc_Date_to_Text(Z_int year, Z_int month, Z_int day, Z_int lang) { charptr string; if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language; if (DateCalc_check_date(year,month,day) and ((string = (charptr) malloc(32)) != NULL)) { if (DateCalc_Day_of_Week_Abbreviation_[lang][0][0] != '\0') { sprintf((char *)string,"%.3s %d-%.3s-%d", DateCalc_Day_of_Week_Abbreviation_[lang][DateCalc_Day_of_Week(year,month,day)], day,DateCalc_Month_to_Text_[lang][month],year); return(string); } else { sprintf((char *)string,"%.3s %d-%.3s-%d", DateCalc_Day_of_Week_to_Text_[lang][DateCalc_Day_of_Week(year,month,day)], day,DateCalc_Month_to_Text_[lang][month],year); return(string); } } return(NULL); } charptr DateCalc_English_Ordinal(charptr result, Z_int number) { N_int length; N_int digit; sprintf((char *)result, "%d", number); if ((length = strlen((char *)result))) { if ( not ( ( ((length > 1) and (result[length-2] != '1')) or (length == 1) ) and ( (digit = (N_int)(result[length-1] XOR '0')) <= 3 ) ) ) { digit = 0; } sprintf( (char *)(result+length), "%s", DateCalc_English_Ordinals_[digit] ); } return(result); } charptr DateCalc_Date_to_Text_Long(Z_int year, Z_int month, Z_int day, Z_int lang) { charptr string; blockdef(buffer,64); if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language; if (DateCalc_check_date(year,month,day) and ((string = (charptr) malloc(64)) != NULL)) { switch (lang) { case 1: sprintf( (char *)string, (char *)DateCalc_Date_Long_Format_[lang], DateCalc_Day_of_Week_to_Text_[lang] [DateCalc_Day_of_Week(year,month,day)], DateCalc_Month_to_Text_[lang][month], DateCalc_English_Ordinal(buffer,day), year ); break; case 12: sprintf( (char *)string, (char *)DateCalc_Date_Long_Format_[lang], year, DateCalc_Month_to_Text_[lang][month], day, DateCalc_Day_of_Week_to_Text_[lang] [DateCalc_Day_of_Week(year,month,day)] ); break; default: sprintf( (char *)string, (char *)DateCalc_Date_Long_Format_[lang], DateCalc_Day_of_Week_to_Text_[lang] [DateCalc_Day_of_Week(year,month,day)], day, DateCalc_Month_to_Text_[lang][month], year ); break; } return(string); } return(NULL); } charptr DateCalc_Calendar(Z_int year, Z_int month, boolean orthodox, Z_int lang) { blockdef(buffer,64); charptr string; charptr cursor; Z_int first; Z_int last; Z_int day; if ((lang < 1) or (lang > DateCalc_LANGUAGES)) lang = DateCalc_Language; string = (charptr) malloc(256); if (string == NULL) return(NULL); cursor = string; DateCalc_Newline(&cursor,1); sprintf((char *)buffer,"%s %d", DateCalc_Month_to_Text_[lang][month],year); *buffer = DateCalc_ISO_UC(*buffer); DateCalc_Center(&cursor,buffer,27); if (DateCalc_Day_of_Week_Abbreviation_[lang][0][0] != '\0') { if (orthodox) sprintf((char *)cursor,"%3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s\n", DateCalc_Day_of_Week_Abbreviation_[lang][7], DateCalc_Day_of_Week_Abbreviation_[lang][1], DateCalc_Day_of_Week_Abbreviation_[lang][2], DateCalc_Day_of_Week_Abbreviation_[lang][3], DateCalc_Day_of_Week_Abbreviation_[lang][4], DateCalc_Day_of_Week_Abbreviation_[lang][5], DateCalc_Day_of_Week_Abbreviation_[lang][6]); else /* conform to ISO standard */ sprintf((char *)cursor,"%3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s\n", DateCalc_Day_of_Week_Abbreviation_[lang][1], DateCalc_Day_of_Week_Abbreviation_[lang][2], DateCalc_Day_of_Week_Abbreviation_[lang][3], DateCalc_Day_of_Week_Abbreviation_[lang][4], DateCalc_Day_of_Week_Abbreviation_[lang][5], DateCalc_Day_of_Week_Abbreviation_[lang][6], DateCalc_Day_of_Week_Abbreviation_[lang][7]); } else { if (orthodox) sprintf((char *)cursor,"%3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s\n", DateCalc_Day_of_Week_to_Text_[lang][7], DateCalc_Day_of_Week_to_Text_[lang][1], DateCalc_Day_of_Week_to_Text_[lang][2], DateCalc_Day_of_Week_to_Text_[lang][3], DateCalc_Day_of_Week_to_Text_[lang][4], DateCalc_Day_of_Week_to_Text_[lang][5], DateCalc_Day_of_Week_to_Text_[lang][6]); else /* conform to ISO standard */ sprintf((char *)cursor,"%3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s\n", DateCalc_Day_of_Week_to_Text_[lang][1], DateCalc_Day_of_Week_to_Text_[lang][2], DateCalc_Day_of_Week_to_Text_[lang][3], DateCalc_Day_of_Week_to_Text_[lang][4], DateCalc_Day_of_Week_to_Text_[lang][5], DateCalc_Day_of_Week_to_Text_[lang][6], DateCalc_Day_of_Week_to_Text_[lang][7]); } cursor += 28; first = DateCalc_Day_of_Week(year,month,1); last = DateCalc_Days_in_Month_[DateCalc_leap_year(year)][month]; if (orthodox) { if (first == 7) first = 0; } else { first--; } if (first) DateCalc_Blank(&cursor,(first<<2)-1); for ( day = 1; day <= last; day++, first++ ) { if (first > 0) { if (first > 6) { first = 0; DateCalc_Newline(&cursor,1); } else DateCalc_Blank(&cursor,1); } sprintf((char *)cursor," %2d",day); cursor += 3; } DateCalc_Newline(&cursor,2); return(string); } void DateCalc_Dispose(charptr string) { free((voidptr) string); } charptr DateCalc_Version(void) { return( (charptr) "6.1" ); } /*****************************************************************************/ /* VERSION: 6.1 */ /*****************************************************************************/ /* VERSION HISTORY: */ /*****************************************************************************/ /* */ /* Version 6.1 15.10.09 Fixed Polish language entries. */ /* Version 6.0 07.10.09 +: norm_delta_ymdhms, add_norm_delta_ymd[hms]. */ /* Version 5.8 12.09.09 Added "norm_delta_ymd()". */ /* Version 5.7 23.08.09 Fixed Dutch "oktober", Portuguese DOW abbrevs. */ /* Version 5.6 28.07.09 Made the module MacOS X compatible. */ /* Version 5.5 skipped due to an unauthorized upload by someone else. */ /* Version 5.4 03.10.04 Added compiler directives for C++. */ /* Version 5.3 29.09.02 No changes. */ /* Version 5.2 18.09.02 No changes. */ /* Version 5.1 08.09.02 Added conditional changes for MacOS/MacPerl. */ /* Version 5.0 10.10.01 New YMD/HMS functions, replaced , ... */ /* Version 4.3 08.01.00 decode_date_??: (yy < 70 ? 20yy : 19yy) */ /* Version 4.2 07.09.98 No changes. */ /* Version 4.1 08.06.98 Fixed bug in "add_delta_ymd()". */ /* Version 4.0 12.05.98 Major rework. Added multi-language support. */ /* Version 3.2 15.06.97 Added "week_of_year()". */ /* Version 3.1 12.06.97 No significant changes. */ /* Version 3.0 16.02.97 Changed conventions for unsuccessful returns. */ /* Version 2.3 22.11.96 Fixed unbalanced "malloc" and "free". */ /* Version 2.2 26.05.96 No significant changes. */ /* Version 2.1 26.05.96 Fixed HH MM SS parameter checks. */ /* Version 2.0 25.05.96 Added time calculations. Major rework. */ /* Version 1.6 20.04.96 Not published. */ /* Version 1.5 14.03.96 No significant changes. */ /* Version 1.4 11.02.96 No significant changes. */ /* Version 1.3 10.12.95 Added "days_in_month()". */ /* Version 1.2b 27.11.95 No significant changes. */ /* Version 1.2a 21.11.95 Fix for type name clashes. */ /* Version 1.1 18.11.95 Fix for type name clashes. */ /* Version 1.01 16.11.95 Improved compliance w/ programming standards. */ /* Version 1.0 14.11.95 First version under UNIX (with Perl module). */ /* Version 0.9 01.11.93 First version of C library under MS-DOS. */ /* */ /*****************************************************************************/ /* AUTHOR: */ /*****************************************************************************/ /* */ /* Steffen Beyer */ /* mailto:STBEY@cpan.org */ /* http://www.engelschall.com/u/sb/download/ */ /* */ /*****************************************************************************/ /* COPYRIGHT: */ /*****************************************************************************/ /* */ /* Copyright (c) 1993 - 2009 by Steffen Beyer. */ /* All rights reserved. */ /* */ /*****************************************************************************/ /* LICENSE: */ /*****************************************************************************/ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License as published by the Free Software Foundation; either */ /* version 2 of the License, or (at your option) any later version. */ /* */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* Library General Public License for more details. */ /* */ /* You should have received a copy of the GNU Library General Public */ /* License along with this library; if not, write to the */ /* Free Software Foundation, Inc., */ /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */ /* */ /*****************************************************************************/ #endif