home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* (c) 1987 by James N. Seed, Atlanta, GA - all rights reserved. */
- /* */
- /* Permission is hereby granted to freely distribute and use this */
- /* document for whatever purpose provided that: */
- /* */
- /* A) this copyright notice, in its entirety, including the author's */
- /* name (above) is not removed or altered, */
- /* */
- /* B) it, and/or any or all of the algorithms it contains, is not */
- /* sold or distributed FOR MONETARY PROFIT without the express */
- /* written consent of the author and owner of the copyright, */
- /* James Seed, and */
- /* */
- /* C) a one-time compensatory fee of $10 be paid the author in the */
- /* event that any or all of these algorithms are employed in any */
- /* product sold for profit. This fee must be paid PRIOR to */
- /* distribution of said product, and should be sent to: */
- /* */
- /* James Seed */
- /* 2752 Twin Brooks Dr., apt #4 */
- /* Atlanta, GA 30319 */
- /************************************************************************/
-
- /************************************************************************/
- /* All of these routines were written entirely in machine independant, */
- /* compiler independant, standard ( ANSI ) "C" language. */
- /* */
- /* The only exceptions to the machine independance of the source occur */
- /* in "jtog" and "fulldte", because they assume the usage of the ASCII */
- /* character set. */
- /************************************************************************/
-
- /************************************************************************/
- /* Notes: For those of you that don't already know, a "julian" date */
- /* ===== is simply the number of days that has transpired since */
- /* some arbitrary point in time. For these routines, that */
- /* arbitrary point in time is 01/00/0000, or the 0th day A.D. */
- /* A "gregorian" date is simply a date expressed in terms of */
- /* the month, day, and year, which is what we use today. */
- /* */
- /* The name "julian" comes from the creator of the original */
- /* concept, Julius Caesar, and I think the name "gregorian" */
- /* comes from Pope Gregory, who sanctified the continued use */
- /* of the original Pagan concept, although I'm not sure... */
- /* */
- /* All of these routines assume that year 0000 is a leap year. */
- /* */
- /* In the interest of portability, I have not declared any */
- /* "unsigned long" variable types, because some compilers do */
- /* not support it. The "docs in the box" for each routine, */
- /* however, specify which long integers should be unsigned, */
- /* so you can go ahead and change the source to reflect this */
- /* if you like. It will only make a difference if you are */
- /* working with HUGE date numbers ( ie: past year 9999 ) or */
- /* in the ( unlikely? ) event that you erroneously input a */
- /* negative julian date. ( a definite no no ) */
- /************************************************************************/
-
- /************************************************************************/
- /* *** gtoj.c *** */
- /* */
- /* This function converts a gregorian date, in the ( month, day, year ) */
- /* format, into its respective julian, or day number, equivalent. */
- /* ( 1 = 1st day AD ) */
- /* */
- /* The legal input values, in their proper order, are: */
- /* */
- /* month = 1 to 12 ( unsigned int ) */
- /* day = 1 to 31 ( unsigned int ) */
- /* year = 0 to 9999 ( unsigned int ) */
- /* */
- /* The return value of the function is the julian day number */
- /* expressed as an unsigned long integer. */
- /* */
- /************************************************************************/
-
- long gtoj( m, d, y )
-
- unsigned int m, d, y;
-
- {
- y += ( m += 9 ) / 12 + 399;
- m %= 12;
-
- return ( (long)y*365 + y/4 - y/100 + y/400 + (153*m+2)/5 + d - 146037 );
- }
-
- /************************************************************************/
- /* *** jtog.c *** */
- /* */
- /* This function converts a julian day number ( 1 = 1st day AD ), into */
- /* either a gregorian date character string, in any one of the four */
- /* formats described below, or an array of three integers representing */
- /* the month, day, and year, respectively, of the equivalent gregorian */
- /* date. Storage for the output is provided by the calling routine. */
- /* */
- /* The input values, in their proper order, are: */
- /* */
- /* 1. the julian date to be converted, ( unsigned long ) */
- /* */
- /* 2. a pointer to the output array, ( char * ) */
- /* */
- /* 3. the format code ( described below ) */
- /* specifying the desired output format. ( unsigned int ) */
- /* */
- /* The format codes are defined as follows: */
- /* */
- /* CODE - EXPLANATION - */
- /* */
- /* 0 - output array will hold three integers defined as: */
- /* */
- /* array[0] = month ( mm ) */
- /* array[1] = day ( dd ) */
- /* array[2] = year ( yyyy ) */
- /* */
- /* If this format option is used, a type cast will have to */
- /* be performed on the output pointer to convert it to the */
- /* appropriate pointer type. ( see example below ) */
- /* */
- /* 1 - output string will hold a character string in the */
- /* format "mmddyy" ( minimum - char string[7] ) */
- /* */
- /* 2 - output string will hold a character string in the */
- /* format "mmddyyyy" ( minimum - char string[9] ) */
- /* */
- /* 3 - output string will hold a character string in the */
- /* format "mm/dd/yy" ( minimum - char string[9] ) */
- /* */
- /* 4 - output string will hold a character string in the */
- /* format "mm/dd/yyyy" ( minimum - char string[11] ) */
- /* */
- /* NOTE - input of any format code not listed above will be */
- /* interpreted as code 0. */
- /* */
- /* The function returns a character pointer to the output array. */
- /* ______________________________________________________________ */
- /* | *** example of integer array output *** | */
- /* | | */
- /* | int month, dte_array[3]; | */
- /* | long julian = 548784; | */
- /* | | */
- /* | month = ( (int *)jtog( julian, (char *)dte_array, 0 ) )[0]; | */
- /* |______________________________________________________________| */
- /* */
- /* WARNING - the output array pointed to must be dimensioned */
- /* accordingly or a memory overwrite will occur. */
- /************************************************************************/
-
- char *jtog( julian, date, fmt )
-
- long julian;
- char *date;
- unsigned int fmt;
-
- {
- int month, day, year, i;
- long numdte, indx = !( fmt & 1 ) * 9900 + 100;
-
- year = ( julian += 146037 ) * 400 / 146097;
- julian -= (long)year*365 + year/4 - year/100 + year/400;
- year += julian / ( i = 366 - !!( ( year + 1 ) % 4 ) );
-
- if ( !( julian %= i ) ) julian = 365 + !( year % 4 ), --year;
-
- year += ( month = ( day = (int)julian * 5 - 3 ) / 153 + 2 ) / 12 - 400;
- month = month % 12 + 1;
- day = day % 153 / 5 + 1;
-
- if ( fmt && fmt < 5 )
- {
- numdte = (long)month * 100 * indx + day * indx + year % indx;
- for ( indx *= 10000, i = 0; indx > 1; ++i )
- date[i] = ( fmt > 2 && ( i == 2 || i == 5 ) ) ? '/'
- : (char)( numdte / ( indx /= 10 ) % 10 + 48 );
- date[i] = '\0';
- }
- else
- {
- ((int *)date)[0] = month;
- ((int *)date)[1] = day;
- ((int *)date)[2] = year;
- }
-
- return( date );
- }
-
- /************************************************************************/
- /* *** dow.c *** */
- /* */
- /* This function returns the numerical day-of-week of a julian */
- /* date, input as an unsigned long integer. */
- /* */
- /* The return value of the function is the day of the week expressed */
- /* as an unsigned integer value, and is enumerated as follows: */
- /* */
- /* Sunday - 0 */
- /* Monday - 1 Thursday - 4 */
- /* Tuesday - 2 Friday - 5 */
- /* Wednesday - 3 Saturday - 6 */
- /* */
- /************************************************************************/
-
- int dow( julian )
-
- long julian;
-
- {
- return( (int)( ( julian + 5 ) % 7 ) );
- }
-
- /************************************************************************/
- /* *** fulldte.c *** */
- /* */
- /* This function converts a julian day number ( 1 = 1st day AD ), */
- /* into an equivalent gregorian date descriptive phraze of the form: */
- /* */
- /* "Wednesday September 16, 1987" ( example ) */
- /* */
- /* The input values, in their proper order, are: */
- /* */
- /* 1. the julian date to be converted ( unsigned long ) */
- /* */
- /* 2. a pointer to the output character string. ( char * ) */
- /* */
- /* The length, in ASCII characters, of the output string is returned */
- /* by the function upon completion, expressed as an unsigned integer. */
- /* */
- /* WARNING - the character string pointed to must be dimensioned to */
- /* at least 29 characters, or a memory overwrite may occur. */
- /* */
- /************************************************************************/
-
- int fulldte( julian, dtestr )
-
- long julian;
- char *dtestr;
-
- {
- static char *daynme[7] = { "Sunday", "Monday", "Tuesday",
- "Wednesday", "Thursday", "Friday",
- "Saturday" };
- static char *mosnme[12] = { "January", "February", "March",
- "April", "May", "June",
- "July", "August", "September",
- "October", "November", "December" };
-
- static char **text[2] = { daynme, mosnme };
-
- int i, j, k, strt, dtearr[4];
-
- dtearr[0] = dow( julian );
- jtog( julian, (char *)&dtearr[1], 0 );
- --dtearr[1];
-
- for ( i = j = k = 0; i < 2; k = 0, ++i )
- {
- while ( text[i][dtearr[i]][k] )
- dtestr[j++] = text[i][dtearr[i]][k++];
- dtestr[j++] = ' ';
- }
-
- for ( strt = 0, i = 2; i < 4; ++i )
- {
- for ( k = 1000; k; dtearr[i] %= k, k /= 10 )
- {
- if ( strt = strt || dtearr[i] / k )
- dtestr[j++] = (char)( dtearr[i] / k + 48 );
- }
-
- if ( i == 2 ) dtestr[j++] = ',';
-
- dtestr[j++] = ' ';
- }
-
- dtestr[--j] = '\0';
-
- return( j );
- }
-
- /************************************************************************/
- /* *** daycnt.c *** */
- /* */
- /* This function returns the number of days of the specified type that */
- /* exist between the two julian dates input, expressed as an signed */
- /* long integer. */
- /* */
- /* The input values to the function, in their proper order, are: */
- /* */
- /* 1. the beginning julian date ( unsigned long ) */
- /* */
- /* 2. the ending julian date ( unsigned long ) */
- /* */
- /* 3. the numerical code representing the type */
- /* of days to be counted ( described below ) ( unsigned int ) */
- /* */
- /* The following is a list of the codes used to define the */
- /* type of days that are to be counted: */
- /* */
- /* CODE - EXPLANATION - */
- /* */
- /* 0 - all days */
- /* */
- /* 1 - all days excluding Sundays */
- /* */
- /* 2 - all days excluding weekends ( Saturdays and Sundays ) */
- /* */
- /* NOTE - input of any code not listed above will be */
- /* interpreted as code 0. */
- /* */
- /************************************************************************/
-
- long daycnt( juldt1, juldt2, excl )
-
- long juldt1, juldt2;
- unsigned int excl;
-
- {
- int eff = 7 - ( excl = excl > 2 ? 0 : excl );
-
- if ( !excl-- ) return( juldt2 - juldt1 );
-
- if ( juldt1 > juldt2 ) return( -daycnt( juldt2, juldt1, ++excl ) );
- else
- {
- juldt1 -= !dow( juldt1 ) + ( excl && !( dow( juldt1 ) % 6 ) );
- juldt2 -= !dow( juldt2 ) + ( excl && !( dow( juldt2 ) % 6 ) );
- }
-
- return( ( juldt2 - juldt1 ) / 7 * eff +
- ( dow( juldt2 ) - dow( juldt1 ) + eff ) % eff );
- }
-
- /************************************************************************/
- /* *** newdate.c *** */
- /* */
- /* This function returns a new julian date, expressed as an unsigned */
- /* long integer, arrived at by adding a specified number of days of a */
- /* specified type to the starting julian date input. */
- /* */
- /* In short, it adds days to a date to get a new date. */
- /* */
- /* The input values to the function, in their proper order, are: */
- /* */
- /* 1. the beginning julian date ( unsigned long ) */
- /* */
- /* 2. the number of days to be added ( signed long ) */
- /* */
- /* 3. the numerical code representing the type */
- /* of days to be added ( described below ) ( unsigned int ) */
- /* */
- /* The following is a list of the codes used to define the */
- /* type of days that are to be added to the start date: */
- /* */
- /* CODE - EXPLANATION - */
- /* */
- /* 0 - weekdays and weekends (all days) */
- /* */
- /* 1 - weekdays and Saturdays only (Sundays skipped over) */
- /* */
- /* 2 - weekdays only (weekends skipped over) */
- /* */
- /* NOTE - input of any code not listed above will be */
- /* interpreted as code 0. */
- /* */
- /************************************************************************/
-
- long newdate( juldte, days, incl )
-
- long juldte, days;
- unsigned int incl;
-
- {
- int eff = 7 - ( incl = incl > 2 ? 0 : incl ), rvrse = 0;
-
- if ( !incl-- ) return( juldte + days );
-
- if ( days < 0 )
- {
- rvrse = eff + 1;
- juldte += !dow( juldte ) + 2 * ( incl && !( 6 - dow( juldte ) ) );
- }
- else juldte -= !dow( juldte ) + ( incl && !( dow( juldte ) % 6 ) );
-
- return( juldte + days / eff * 7 + days % eff + ++incl *
- ( ( dow( juldte ) + days % eff - rvrse ) / ( eff + 1 ) ) );
- }