[comp.sys.amiga] New ShowDate

rokicki@polya.Stanford.EDU (Tomas G. Rokicki) (08/19/88)

/*
 *   Written by Tomas Rokicki of Radical Eye Software.
 *
 *   Here's an updated ShowDate() routine, as requested by Rob
 *   Peck.  This one even has some limited explanations of how
 *   it works!  It sets the day of week as well as month, day,
 *   and year from the values returned by DateStamp().
 *
 *   Note that the original code published in Peck's book, would
 *   fail for dates prior to 1984.  When compiled with 16-bit
 *   integers, it would fail for dates after 2007.  The current
 *   code will work with any size integer from Amiga day 0 until
 *   March 1, 2100.
 */
int w, m, d, y ;
main(argc, argv)
int argc ;
char *argv[] ;
{
   long v[3] ;

   DateStamp(v) ;
   ShowDate(v) ;
}
static char *months[]={"", "January", "February", "March", "April", "May",
   "June", "July", "August", "September", "October", "November",
   "December"} ;
static char *days[]={"", "Sunday", "Monday", "Tuesday", "Wednesday",
   "Thursday", "Friday", "Saturday"} ;
/*
 *   This routine sets global variables $m$, $d$, $y$, and $w$
 *   to the current month, day, year, and day of week.  Months,
 *   days, and day of weeks all start at 1 with first members
 *   January, the first, and Sunday, respectively.
 */
ShowDate(v)
long *v ;
{
   long n ;
/*
 *   Set $n$ to the number of days since Amiga day -671, which is
 *   March 1, 1976.  It's easier to figure years starting in March,
 *   since then the lengths of the months are 31, 30, 31, 30, 31,
 *   31, 30, 31, 30, 31, 31, 28.  This is almost linear.
 */
   n = v[0] + 671 ;
/*
 *   The easiest is the weekday.  This is simply the number of days
 *   modulo 7, corrected for the start date.  March 1, 1976 was a
 *   Monday, so we add 1 to get back to a Sunday, take the modulo,
 *   and add one to start our days on Sunday.
 */
   w = (n + 1) % 7 + 1 ;
/*
 *   There are exactly 1461 days every four years, until 2100, which
 *   is the first year divisible by 4 that is not a leap year AA
 *   (After Amiga.)  This gives the years lengths of 365 (1976),
 *   365 (1977), 365 (1978), and 366 (1979).  Note that this is
 *   correct because we start our years in March, so 1979 is the
 *   leap year.
 */
   y = (4 * n + 3) / 1461 ;
/*
 *   We now subtract off the years (see them melt off her face.)
 *   We use a long constant for 16-bit systems.  Again we use the
 *   fact that the leap year is the fourth year, not the first.
 */
   n -= 1461L * y / 4 ;
/*
 *   Now we can adjust the year to the proper value by adding
 *   1976.
 */
   y += 1976 ;
/*
 *   We calculate the month.  Since we start in March, the length
 *   of the months are always 30 or 31, except for the last month,
 *   which is shorter.  This is fortunate, as it allows us to use
 *   a simple mathematical formula for the month.  The lengths of
 *   the months are (31, 30, 31, 30, 31), repeated three times and
 *   the end lopped off.  So, our slope is 153/5.  An intercept of
 *   2 gives us the 31 and 30 lengths.
 */
   m = (5 * n + 2) / 153 ;
/*
 *   And now we subtract off the months.  Oh, yeah, we add 1 because
 *   the first day of each month is the first, not the zeroth.
 */
   d = n - (153 * m + 2) / 5 + 1 ;
/*
 *   Now we convert from March-based years back to January-based
 *   years.  We add 2 for this shift, and another 1 to give us
 *   January = 1 through December = 12.
 */
   m += 3 ;
/*
 *   And, if we've gone over 12, we increment the year.
 */
   if (m > 12) {
      y++ ;
      m -= 12 ;
   }
/*
 *   That's it!
 */
   printf("%s, %s %d, %d\n", days[w], months[m], d, y) ;
}