Path: utzoo!attcan!uunet!wyse!vsi1!ames!elroy!peregrine!zardoz!dhw68k!jimb From: jimb@dhw68k.cts.com (Jim Bacon) Newsgroups: comp.sources.wanted Subject: Date manipulation routines (repost) Keywords: julian dates gregorian calendar Message-ID: <11858@dhw68k.cts.com> Date: 20 Sep 88 03:19:59 GMT Organization: Wolfskill residence; Anaheim, CA (USA) Lines: 305 Here is a re-post of the routines I posted earlier. Several of you have informed me of a grunged post, this should be better. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh'lldates.c' <<'END_OF_FILE' X/***************************************************************************** X * X * MODULE NAME: datelib.c X * X * FUNCTIONS: long juldate(), julcmp() X * int isleap(), zeller() X * char *julrev() X * X * REVISION HISTORY: X * Version/--date--/-by-/reason------------------------------------------ X * 1.0 12/28/85 jb julian date function library X * 1.1 9/10/88 jgb cleaned up for UNIX X * X * DESCRIPTION: routines for date manipulations X * X ****************************************************************************/ X X#include X#include X#include X X#define INT(x) ((int)(x)) X X#define MO 0 X#define DAY 1 X#define YR 2 X X#define BAD_DATE 0 X#define BAD_DAY 1 X#define BAD_MO 2 X#define BAD_YR 3 X#define BAD_DIGIT 4 X#define BAD_JUL 5 X Xchar *wk_day[] = { X "ERROR", "Sunday", "Monday", "Tuesday", "Wednesday", X "Thursday", "Friday", "Saturday" }; X X Xint days_mo[] = { X 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; X X Xint _julerr; /* global error return */ X X/** X * FUNCTION NAME: int isleap() X * X * DESCRIPTION: determines whether a given year is leap or not. X * X * INPUTS: int year X * X * OUTPUTS: TRUE if leap, otherwise FALSE X */ X Xint isleap(year) Xint year; X{ X return( year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ); X} X X X/** X * FUNCTION NAME: long juldate() X * X * DESCRIPTION: converts a date string to number of days from a X * given base year. X * X * INPUTS: char *date pointer to date string X * in mm/dd/yy or yyyy format X * int base base year, >= 1900 X * X * OUTPUTS: number of days from 1/1/base or 0 if error X */ X Xlong juldate(date, base) Xchar *date; Xint base; X{ X char c; X int mdy[3], n; X long retjul; X X for ( n = 0; n < 3; n++) mdy[n] = 0; X _julerr = 0; X n = 0; X days_mo[2] = 28; /* fix possible prior feb 29 */ X X while ( c = *date++) { X if ( c == '-' || c == '/' ) { X n++; X continue; X } X if ( !isdigit(c) ) { X _julerr = BAD_DIGIT; X return(BAD_DATE); X } X mdy[n] = 10 * mdy[n] + (c - '0'); X } X X if ( mdy[MO] < 1 || mdy[MO] > 12 ) { X _julerr = BAD_MO; X return(BAD_DATE); X } X X if ( mdy[YR] < 100 ) { X if ( mdy[YR] < base - 1900) X mdy[YR] += 2000; X else X mdy[YR] += 1900; X } X X if ( mdy[YR] < base ) { X _julerr = BAD_YR; X return(BAD_DATE); X } X X days_mo[2] = isleap(mdy[YR]) ? 29 : 28; X X if ( mdy[DAY] < 1 || mdy[DAY] > days_mo[mdy[MO]] ) { X _julerr = BAD_DAY; X return(BAD_DATE); X } X X retjul = mdy[DAY]; X X for (n = 1; n < mdy[MO]; n++) X retjul += days_mo[n]; X X for (n = base; n < mdy[YR]; n++) X retjul += ( isleap(n) ? 366 : 365 ); X X return(retjul); X} X X X/** X * FUNCTION NAME: long julcmp() X * X * DESCRIPTION: returns the numbers of days between 2 dates. X * negative if str1 > str2. X * X * INPUTS: char *str1,*str2 date strings X * X * OUTPUTS: difference between julian dates based on common X * year of 1900. X * X * PROBLEMS: both input dates must be >= 1/1/1900. X * returns 0 if bad date strings are input. X */ X Xlong julcmp(str1, str2) Xchar *str1, *str2; X{ X long jul1, jul2; X X _julerr = 0; X X if ( !(jul1 = juldate(str1, 1900)) ) X return(BAD_DATE); X X if ( !(jul2 = juldate(str2, 1900)) ) X return(BAD_DATE); X X return(jul2 - jul1); X} X X X/** X * FUNCTION NAME: char *julrev() X * X * DESCRIPTION: returns a date string from an unsigned julian integer X * X * INPUTS: long jul julian number X * int year base year X * X * OUTPUTS: pointer to date string. NULL if negative jul X */ X Xchar *julrev(jul, year) Xlong jul; Xint year; X{ X static char date[11]; X int days_year, n = 1; X X memset(date, '\0', sizeof(date)); X X days_mo[2] = 28; X X if ( jul > 0 ) X _julerr = 0; X else { X _julerr = BAD_JUL; X return(NULL); X } X X do { X days_year = isleap(year) ? 366 : 365; X year++; X jul -= days_year; X } while ( jul > 0 ); X X year--; X jul += days_year; X X if ( days_year == 366 ) X days_mo[2] = 29; X X do X jul -= days_mo[n++]; X while ( jul > 0 ); X X --n; X jul += days_mo[n]; X X year = (year > 1999 ? year : year - 1900); X X sprintf(date, "%02d/%02d/%02d", n, (int)jul, year); X X X return(date); X} X X X/** X * FUNCTION NAME: int *zeller() X * X * DESCRIPTION: produces zeller congruence give an input date. X * X * INPUTS: char *date mm/dd/yy or mm/dd/yyyy X * X * OUTPUTS: int n sun = 1, sat = 7, 0 if error X */ X Xint zeller(date) Xchar *date; X{ X X char c; X int mdy[3], month, year, century, offset, n = 0; X X _julerr = 0; X X mdy[DAY] = mdy[MO] = mdy[YR] = 0; X X while ( c = *date++) { X if ( c == '-' || c == '/' ) { X n++; X continue; X } X if ( !isdigit(c) ) { X _julerr = BAD_DIGIT; X return(BAD_DATE); X } X mdy[n] = 10 * mdy[n] + (c - '0'); X } X X mdy[YR] = (mdy[YR] < 100 ? mdy[YR] + 1900 : mdy[YR]); X X if ( mdy[MO] > 2 ) { X month = mdy[MO] - 2; X year = mdy[YR]; X } else X { X month = mdy[MO] + 10; X year = mdy[YR] - 1; X } X X century = year / 100; X offset = year % 100; X X n = INT((13 * month - 1) / 5) + mdy[DAY] + offset + INT(offset / 4) X + INT(century / 4) - 2 * century + 77; X n = n - 7 * INT(n / 7); X X return(n + 1); X} END_OF_FILE if test 4967 -ne `wc -c <'lldates.c'`; then echo shar: \"'lldates.c'\" unpacked with wrong size! fi # end of 'lldates.c' fi echo shar: End of shell archive. exit 0