Path: utzoo!attcan!uunet!ccicpg!felix!dhw68k!jimb From: jimb@dhw68k.cts.com (Jim Bacon) Newsgroups: comp.sources.wanted Subject: Date manipulation routines (Julian, etc.) Keywords: Julain dates Zeller Message-ID: <11466@dhw68k.cts.com> Date: 11 Sep 88 08:32:40 GMT Reply-To: jim@anacom1.tcc.com (Jim Bacon) Distribution: na Organization: Wolfskill residence; Anaheim, CA (USA) Lines: 239 I have seen at least two requests for date manipulation routines lately. Here is the library that I use. It is based heavily on the routines found in "Common C Functions" (Que). Because it allows Julian dates based on any given year, it easily allows for math to be performed on dates. Notice also that it will work with dates without leading zeroes in the MM/DD/YY format. I can be reached at turnkey!anacom1!jim or jim@anacom1.tcc.com Enjoy! #! /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 functiX#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 * 3], n; X long retjul; X X for ( n = 0; n < 3; n++) mdy[n] = 0; X _julerr = 0; X n = 0; 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 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 += d 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; tes.c'`; then echo shar: \"'lldates.c'\" unpacked with wrong size! fi # end of 'lldates.c' fi echo shar: End of shell archive. exit 0