home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / SCALDATE.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  2KB  |  56 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*
  4. ** scalar date routines    --    public domain by Ray Gardner
  5. ** Numerically, these will work over the range 1/01/01 thru 14699/12/31.
  6. ** Practically, these only work from the beginning of the Gregorian 
  7. ** calendar thru 14699/12/31.  The Gregorian calendar took effect in
  8. ** much of Europe in about 1582, some parts of Germany in about 1700, in
  9. ** England and the colonies in about 1752ff, and in Russia in 1918.
  10. */
  11.  
  12. #include "scaldate.h"
  13.  
  14. int isleap (unsigned yr)
  15. {
  16.    return yr % 400 == 0 || (yr % 4 == 0 && yr % 100 != 0);
  17. }
  18.  
  19. static unsigned months_to_days (unsigned month)
  20. {
  21.    return (month * 3057 - 3007) / 100;
  22. }
  23.  
  24. static long years_to_days (unsigned yr)
  25. {
  26.    return yr * 365L + yr / 4 - yr / 100 + yr / 400;
  27. }
  28.  
  29. long ymd_to_scalar (unsigned yr, unsigned mo, unsigned day)
  30. {
  31.    long scalar;
  32.    scalar = day + months_to_days(mo);
  33.    if ( mo > 2 )                         /* adjust if past February */
  34.       scalar -= isleap(yr) ? 1 : 2;
  35.    yr--;
  36.    scalar += years_to_days(yr);
  37.    return scalar;
  38. }
  39.  
  40. void scalar_to_ymd (long scalar, unsigned *yr, unsigned *mo, unsigned *day)
  41. {
  42.    unsigned n;                /* compute inverse of years_to_days() */
  43.  
  44.    for ( n = (unsigned)((scalar * 400L) / 146097L); years_to_days(n) < scalar;)
  45.       n++;                          /* 146097 == years_to_days(400) */
  46.    *yr = n;
  47.    n = (unsigned)(scalar - years_to_days(n-1));
  48.    if ( n > 59 ) {                       /* adjust if past February */
  49.       n += 2;
  50.       if ( isleap(*yr) )
  51.          n -= n > 62 ? 1 : 2;
  52.    }
  53.    *mo = (n * 100 + 3007) / 3057;    /* inverse of months_to_days() */
  54.    *day = n - months_to_days(*mo);
  55. }
  56.