Category : C Source Code
Archive   : C-DATES.ZIP
Filename : C_DATES.C

 
Output of file : C_DATES.C contained in archive : C-DATES.ZIP
/************************************************************************/
/* (c) 1987 by James N. Seed, Dallas, TX - all rights reserved. */
/* */
/* Permission is 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, and */
/* */
/* B) it, and/or any or all of the algorithms it contains, is not */
/* sold, distributed, or used in any form, FOR MONETARY PROFIT, */
/* without the express written consent of the author, named above. */
/************************************************************************/

/************************************************************************/
/* 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;

if ( !julian ) 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 ), sgn = 1;

if ( !excl-- ) return( juldt2 - juldt1 );

if ( juldt1 > juldt2 )
{
juldt1 += juldt2, juldt2 = juldt1 - juldt2;
juldt1 -= juldt2, sgn = -1;

juldt1 += !dow( juldt1 ) + 2 * ( excl && !( 6 - dow( juldt1 ) ) );
juldt2 += !dow( juldt2 ) + 2 * ( excl && !( 6 - dow( juldt2 ) ) );
}
else
{
juldt1 -= !dow( juldt1 ) + ( excl && !( dow( juldt1 ) % 6 ) );
juldt2 -= !dow( juldt2 ) + ( excl && !( dow( juldt2 ) % 6 ) );
}

return( sgn * ( ( 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 ) ) );
}


  3 Responses to “Category : C Source Code
Archive   : C-DATES.ZIP
Filename : C_DATES.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/