home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_11_08
/
twilling
/
excerpts.c
next >
Wrap
Text File
|
1993-02-25
|
3KB
|
87 lines
// EXCERPTS: The two crucial routines from the "JD2GREG.C" module, without
// the auxiliary functions and all the blather.......
/**********************( GREGORIAN CALENDAR MODULE )**************************
Routines for converting between Gregorian Calendar dates and Julian Days, for
validating date input, for date arithmetic, and for learning day of the week
and of the year.
(c) 1991, 1993 by Bob Twilling.
C Users Journal readers may use this code for any purpose.
/----------------------------------------------------------------------------*/
#include <stdlib.h> //for div()
typedef struct { short mo;
short dy;
short yr; } MDY;
/*=======================( MONTH TO DAY-OF-YEAR )===========================/
Given a month, calc day of year up until. Change to #if 0 to save 24 bytes
of near heap at a slight speed cost. */
#if 1
static short m2doy[] =
{ 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337 };
#define M2DOY(mo) (m2doy[mo-1])
#else
#define M2DOY(mo) ((((mo) * 979) >> 5) - 30)
#endif
/*=========================( GREGORIAN TO JD )==============================/
Given a month, day, and year, returns a long integer -- the Julian Day number
at noon of that date. */
extern long greg2jd( short mo, short dy, short yr ) {
short lp;
if ((mo -= 2) <= 0) { mo += 12; yr--; } // 1> Roll-under the date
dy += M2DOY(mo); // 2> Calc day of year
lp = yr >> 2; // 3> Add and subtract leap days
dy += lp;
lp /= 25;
dy -= lp;
dy += lp >> 2;
return (long)yr * 365 + dy + 1721119; } // 4> One div, one mul!
/*=========================( JD TO GREGORIAN )==============================/
Given a long Julian Day and a pointer to a month-day-year structure, fills in
that structure with the calendar date and returns the same pointer to it. */
extern MDY * jd2greg( long jd, MDY * date ) {
unsigned short x, y, d;
div_t sd; //div and mod at the same time
y = 1600; jd -= 2305507; // 1> new origin 0 = 2/29/1600
while (jd > 0) { y += 400; jd -= 146097; } // 2> lop off 400-yr blocks
do { y -= 100; } while ((jd += 36524) < 0); // and add back 100-yr ones
d = (unsigned short)jd; // 3> within 16-bit range now
x = d / 1461; // pity taint no ANSI udiv()
y += x << 2; // note 4-yr blocks
d -= x * 1461; // and lop them off
sd = div( d, 365); // does % and / in same op
date->yr = y + sd.quot; // got years, provisionally
d = ++sd.rem; // 4> day-of-year (base 1)
if (sd.quot == 4) { date->yr--; d = 366; } // case we hit a leap-year
x = ((d + 30) << 5) / 979; // x = month, March is 1
date->dy = d - M2DOY(x); // got day of month
if ((x += 2) > 12) { date->yr++; x -= 12; } // 5> roll around Jan and Feb
date->mo = x; // got month
return(date); }
/*==================================================================ENDIT====*/