home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / alt / sources / 2837 < prev    next >
Encoding:
Text File  |  1992-12-21  |  50.0 KB  |  1,454 lines

  1. Newsgroups: alt.sources
  2. Path: sparky!uunet!spool.mu.edu!agate!linus!linus.mitre.org!truth!jrv
  3. From: jrv@truth.mitre.org (Van Zandt)
  4. Subject: julcal - Julian date functions
  5. Message-ID: <1992Dec21.124514.18885@linus.mitre.org>
  6. Followup-To: alt.sources.d
  7. Keywords: Julian, Gregorian, calendar, dates, struct tm
  8. Sender: news@linus.mitre.org (News Service)
  9. Nntp-Posting-Host: truth.mitre.org
  10. Organization: The MITRE Corp., Bedford, Ma.
  11. Date: Mon, 21 Dec 1992 12:45:14 GMT
  12. Lines: 1440
  13.  
  14. Subject: julcal - Julian date functions in C
  15. Followup-To: alt.sources.d
  16.  
  17. Archive-name: julcal
  18. Submitted-by: jrv@mitre.org (Jim Van Zandt)
  19. Version:    $Id: julcal.c%v 1.10 1992/12/13 03:15:59 jrv Exp jrv $
  20. Keywords: Julian, Gregorian, calendar, dates, struct tm
  21.  
  22. The standard C library routines for dates tend to fail before Jan 1,
  23. 1970.  These routines let you do date calculations back to 4713 B.C. 
  24. using an ordinary struct tm.
  25.  
  26. Like mktime(), juldn() has the side effects of normalizing the values
  27. of the fields tm_mday and tm_mon if they are outside their normal
  28. ranges, and of setting the fields tm_wday (day of week) and tm_yday
  29. (day of year).  However, mktime() is one of the functions that usually 
  30. fails before 1970, and the implementations I tested didn't normalize
  31. correctly, sometimes making spectacular errors.
  32.  
  33. #    This is a shell archive.
  34. #    Remove everything above and including the cut line.
  35. #    Then run the rest of the file through sh.
  36. #----cut here-----cut here-----cut here-----cut here----#
  37. #!/bin/sh
  38. # shar:    Shell Archiver
  39. #    Run the following text with /bin/sh to create:
  40. #    julcal.c
  41. #    julcal.h
  42. #    tjul.c
  43. #    dates.txt
  44. #    data
  45. #    makefile
  46. #    makefile.ux
  47. # This archive created: Sat Dec 19 15:29:40 1992
  48. cat << \SHAR_EOF > julcal.c
  49. /* 
  50.     Julian (sense 1) date routines, handling both Julian (sense 2) and
  51.     Gregorian calendars
  52.  
  53.     SYNOPSIS
  54.         long juldn (struct tm *bdt)
  55.         long juldnj (struct tm *bdt, long Transition)
  56.         long juldnd (struct tm *bdt, struct tm *Transition_date)
  57.  
  58.         struct tm *julcd (long J)
  59.         struct tm *julcdj (long J, long Transition)
  60.         struct tm *julcdd (long J, struct tm *Transition_date)
  61.  
  62.         extern long jul_transition;
  63.  
  64.     DESCRIPTION
  65.  
  66.     juldn* returns the Julian day number (days since Jan 1, 4713 B.C.)
  67.     for the date specified by the struct tm (a broken down time)
  68.     pointed to by 'bdt'.  Only the tm_year, tm_mon, and tm_mday fields
  69.     are examined.  If the month or day fields are out of their normal
  70.     range, they are adjusted.  The tm_wday and tm_yday fields are also
  71.     set.
  72.  
  73.     julcd* returns a pointer to a struct tm filled in with the date
  74.     corresponding to the Julian day number 'J'.  Five fields are set:
  75.     tm_year, tm_mon, tm_mday, tm_wday, and tm_yday.  The pointer is to
  76.     a static structure which is reused on each call.
  77.  
  78.     For both juldn and julcd, the Gregorian calendar is assumed
  79.     provided the Julian day number falls on or after the value in the
  80.     global variable 'jul_transition', otherwise the Julian calendar is
  81.     used.  'jul_transition' is initialized to 2361222 (or September 14,
  82.     1752), as in the United Kingdom and the colonies.  A different
  83.     transition can be specified by Julian day number (for juldnj or
  84.     julcdj) or Gregorian date (for juldnd or julcdd).  Alternatively,
  85.     'jul_transition' can be reset.  If the transition is specified by
  86.     date, ensure it is interpreted as a Gregorian date by using julcdj
  87.     with a small number:
  88.  
  89.         jul_transition = julcdj(&my_transition_date, 1L);
  90.  
  91.     Algorithm is valid from 4713 B.C. to 19,999 A.D.  For caveats,
  92.     see below.
  93.  
  94.     Aside: In a struct tm, the tm_year field is "year-1900".  For the
  95.     year 1 A.D., that would be -1899.  There was no year 0 (the number
  96.     zero had not been invented!), so the previous year was 1 B.C.,
  97.     which is represented by -1900.
  98.  
  99.     HISTORY
  100.  
  101.     $Id: julcal.c%v 1.10 1992/12/13 03:15:59 jrv Exp jrv $
  102.  
  103.     $Log: julcal.c%v $
  104.  * Revision 1.10  1992/12/13  03:15:59  jrv
  105.  * default transition date is that for the United Kingdom
  106.  *
  107.  * Revision 1.9  1992/12/13  03:07:07  jrv
  108.  * juldnj gives correct value even if month is outside normal range.
  109.  * juldnj normalizes mday, month, and year.
  110.  * _juldnj introduced to let julcdj set yday without causing infinite recursion.
  111.  *
  112.  * Revision 1.8  1992/12/08  00:23:38  jrv
  113.  * Test program moved to a separate file.
  114.  *
  115.  * Revision 1.7  1992/12/06  01:57:20  jrv
  116.  * julcd* return pointers to a static struct tm, like localtime and gmtime.
  117.  *
  118.  * Revision 1.6  1992/12/05  23:14:58  jrv
  119.  * The default transition date is a global variable, initialized to 15 Oct 1582.
  120.  * Some variable names changed.  All variables are lower case.
  121.  *
  122.  * Revision 1.5  1992/12/05  22:20:11  jrv
  123.  * juldnd accepts a struct tm (a "broken-down time") instead of a 
  124.  * unique struct.  julcdd produces a struct tm (including tm_wday 
  125.  * and tm_yday fields) instead of a unique struct.
  126.  *
  127.  * Revision 1.4  1992/12/05  20:04:51  jrv
  128.  * Test program prints input values, then computed values.
  129.  * Test program is silent by default.
  130.  *
  131.  * Revision 1.3  1992/12/04  02:57:54  jrv
  132.  * Reformatted to more standard C.
  133.  * Eliminated some redundant typedefs.
  134.  * Type Year is now an int rather than a long.
  135.  * Some variables converted to lower case.
  136.  *
  137.  * Revision 1.2  1992/12/04  02:15:58  jrv
  138.  * A Year is no longer unsigned, so years BC work.
  139.  * Regression test driver added.
  140.  *
  141.  * Revision 1.1  1992/12/04  00:21:37  jrv
  142.  * Initial revision
  143.  *
  144.  
  145.     Translated from Pascal to C by Jim Van Zandt, July 1992.
  146.  
  147.     Error-free translation based on error-free PL/I source
  148.  
  149.     Based on Pascal code copyright 1985 by Michael A. Covington,
  150.     published in P.C. Tech Journal, December 1985, based on formulae
  151.     appearing in Astronomical Formulae for Calculators by Jean Meeus
  152.  
  153.     Reconversion to normal Julian epoch, integer arithmetic and
  154.     4000-year correction by John W. Kennedy
  155.  
  156.     [The 4000-year adjustment is controversial.  It is not mentioned in
  157.     the paper "Calendrical Calculations" by Nachum Dershowitz and
  158.     Edward M.  Reingold in Software Practice and Experience, v 20 n 9
  159.     pp 899-928 (Sep 1990).  I have left it in mainly because it will
  160.     make no difference for a very long time.  - jvz]
  161.  
  162.     Historical exceptions _not_ allowed for in this package:
  163.  
  164.     Until Julius Caesar established the Julian calendar in 45 B.C.,
  165.     calendars were irregular.  This package assumes the Julian calendar
  166.     back to 4713 B.C.
  167.  
  168.     The Julian calendar was altered in 8 B.C.  From 45 B.C. to 8 B.C.,
  169.     the months were
  170.        Jan=31, Feb=29(30), Mar=31, Apr=30, May=31, Jun=30,
  171.        Jul=31, Aug=30,     Sep=31, Oct=30, Nov=31, Dec=30
  172.     This package assumes the month lengths as we know them.
  173.  
  174.     Leap years from 45 B.C.  to 8 A.D.  were miscalculated: (45, 42,
  175.     39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, then none at all until 8
  176.     A.D.) This package assumes leap years every four years, as they
  177.     were meant to have been.
  178.  
  179.     January 1 was not always the first day of the year.  The United
  180.     Kingdom, in particular, started the year on March 25 until 1752. 
  181.     (However, the year ended on December 31, leaving the days between
  182.     in limbo.) This package assumes January 1 is the first day of the
  183.     year.
  184.  
  185.     Leap-year day was originally done by having February 24 (25 from 45
  186.     to 8 B.C.) twice.  This package assumes Leap-year day is February
  187.     29.
  188.  
  189.     "Transition" argument is the first Julian date to be considered as
  190.     belonging to the Gregorian calendar.  Usual values are:
  191.  
  192.     2299161 = October 5/15, 1582,       as in Rome, or
  193.     2361222 = September 3/14, 1752,     as in the United Kingdom 
  194.                                         and the Colonies 
  195.  
  196.     For more on the history of calendars, including transition dates in
  197.     other countries, see Bob Douglas' article in dates.txt.
  198.  
  199. */
  200.  
  201. #include <time.h>
  202. #include "julcal.h"
  203.  
  204. typedef long Julian;
  205. typedef int Year;
  206. typedef int Month;
  207. typedef int Day;
  208.  
  209. Julian jul_transition=JUL_ENGLAND;    
  210.  
  211. /*
  212. Julian juldnj (struct tm *bdt, Julian Transition);
  213. Julian juldn (struct tm *bdt);
  214. Julian juldnd (struct tm *bdt, struct tm *Transition_date);
  215.  
  216. struct tm *julcdj (Julian J, Julian Transition);
  217. struct tm *julcd (Julian J);
  218. struct tm *julcdd (Julian J, struct tm *Transition_date);
  219. */
  220.  
  221. typedef long Work;
  222.  
  223. static Julian 
  224. _juldnj(bdt, Transition) struct tm *bdt; Julian Transition;
  225. {
  226.     Year ay, y, dy;
  227.     Month m;
  228.     Julian jd_julian, jd_gregorian, jd;
  229.  
  230.     y = bdt->tm_year + 1900;
  231.     m = bdt->tm_mon;
  232.  
  233.     dy = m/12;
  234.     y += dy;
  235.     m -= dy*12;
  236.             /* assert( -11 <= m && m <= 11 ) */
  237.     if(m < 0)
  238.         {
  239.         m += 12;
  240.         y--;
  241.         }
  242.             /* assert( 0 <= m && m <= 11 ) */
  243.  
  244.     if ( m < 2 ) 
  245.         {
  246.         m += 1 + 12;
  247.         y--;
  248.         }
  249.     else
  250.         m++;
  251.  
  252.     ay = y + 4716;
  253.     jd_julian = ((1461*(Work)ay) >> 2) + (153*(m + 1)/5)
  254.            + (Work)bdt->tm_mday - 1524;
  255.     jd_gregorian = jd_julian + 2 - y/100 + y/400 - y/4000;
  256.     if ( jd_gregorian >= Transition ) jd = jd_gregorian; 
  257.     else jd = jd_julian;
  258.     return jd;
  259. }
  260.  
  261.     /* this wrapper can call julcdj without causing infinite recursion */
  262. Julian 
  263. juldnj(bdt, Transition) struct tm *bdt; Julian Transition;
  264. {    Julian jd;
  265.     struct tm *normal;
  266.  
  267.     jd = _juldnj(bdt, Transition);
  268.  
  269.     normal = julcdj(jd, Transition);
  270.     bdt->tm_year = normal->tm_year;
  271.     bdt->tm_mon = normal->tm_mon;
  272.     bdt->tm_mday = normal->tm_mday;
  273.     bdt->tm_wday = normal->tm_wday;
  274.     bdt->tm_yday = normal->tm_yday;
  275.  
  276.     return jd;
  277. }
  278.  
  279. Julian 
  280. juldn (bdt) struct tm *bdt; 
  281. {    return juldnj (bdt, jul_transition);
  282. }
  283.  
  284. Julian 
  285. juldnd (bdt, Transition_date) struct tm *bdt; struct tm *Transition_date;
  286. {    return juldnj (bdt, _juldnj (Transition_date, 1L));
  287. }
  288.  
  289. struct tm *
  290. julcdj (jd, Transition) Julian jd; Julian Transition;
  291. {
  292.     Julian aa, ab, a;
  293.     Work b, d, ee;
  294.     Year ay;
  295.     Month em, m;
  296.     Year y;
  297.     struct tm newyears;
  298.     static struct tm date;
  299.  
  300.     memset(&date, 0, sizeof(date));
  301.  
  302.     if ( jd < Transition ) /* Julian Calendar */
  303.         a = (Work)(jd);
  304.     else /* Gregorian Calendar */ 
  305.         {
  306.         aa = jd - 1721120L;
  307.         ab = 31*(aa/1460969L); aa = aa % 1460969L;
  308.         ab = ab + 3*(aa/146097L); aa = aa % 146097L;
  309.         if ( aa == 146096L ) ab = ab + 3; 
  310.         else ab = ab + aa/36524L;
  311.         a = jd + (ab - 2);
  312.         }
  313.     b = a + 1524;
  314.     ay = (Year)((20*b - 2442)/7305);
  315.     d = (1461*(Work)(ay)) >> 2;
  316.     ee = b - d;
  317.     em = (Month)(10000L*ee/306001L);
  318.  
  319.     date.tm_mday = (Day)(ee - 306001L*em/10000L);
  320.  
  321.     m = em - 1;
  322.     if(m > 12) m -= 12;
  323.     date.tm_mon = m - 1;
  324.  
  325.     if ( m > 2 ) y = ay - 4716; 
  326.     else y = ay - 4715;
  327.     date.tm_year = y - 1900;
  328.  
  329.     date.tm_wday = (jd+1)%7;
  330.  
  331.     newyears = date;
  332.     newyears.tm_mon = 0;
  333.     newyears.tm_mday = 1;
  334.     date.tm_yday = jd - _juldnj(&newyears, Transition);
  335.     return &date;
  336. }
  337.  
  338. struct tm *
  339. julcd(jd) Julian jd; 
  340. {    return julcdj (jd, jul_transition);
  341. }
  342.  
  343. struct tm *
  344. julcdd(jd, Transition_date) Julian jd; struct tm *Transition_date; 
  345. {    return julcdj (jd, _juldnj (Transition_date, 1L));
  346. }
  347. SHAR_EOF
  348. cat << \SHAR_EOF > julcal.h
  349. /* 
  350.     declarations for Julian date routines
  351. */
  352.  
  353. #define JUL_ROME 2299161L
  354. #define JUL_ENGLAND 2361222L
  355.  
  356. extern long jul_transition;
  357.  
  358. #ifdef __STDC__
  359.  
  360. long juldnj (struct tm *bdt, long Transition);
  361. long juldn (struct tm *bdt);
  362. long juldnd (struct tm *bdt, struct tm *Transition_date);
  363.  
  364. struct tm *julcdj (long JD, long Transition);
  365. struct tm *julcd (long JD);
  366. struct tm *julcdd (long JD, struct tm *Transition_date);
  367.  
  368. #else
  369.  
  370. long juldnj ();
  371. long juldn ();
  372. long juldnd ();
  373.  
  374. struct tm *julcdj ();
  375. struct tm *julcd ();
  376. struct tm *julcdd ();
  377.  
  378. #endif
  379. SHAR_EOF
  380. cat << \SHAR_EOF > tjul.c
  381. #define MKTIME
  382. /*
  383.     NAME
  384.         tjul - test julcal family of Julian day number programs
  385.  
  386.     SYNOPSIS
  387.         julcal [-v] [datafile]
  388.  
  389.     NOTES
  390.         Default datafile name is "data".  Nothing is printed unless an
  391.         error is found.  
  392.  
  393.     OPTIONS
  394.         -v    verbose: print all comment lines, input data, calculated dates,
  395.             first 10 lines of each set of random tests
  396.  
  397.     INPUT
  398.         A ';' introduces a comment.  
  399.  
  400.         If the first character is 'T', it is followed by the Julian
  401.         date for transition to the Gregorian calendar.  (Initially, the
  402.         transition date is JD2361222 = September 14, 1752, as in England.)
  403.  
  404.         Otherwise, each line has six items:    
  405.             julian_day   year  month  mday  wday  yday
  406.               2299159    1582    10     3    Wed   275
  407.         where 
  408.             julian_day is the number of days since Jan 1, 4713 B.C.
  409.             year is negative for B.C.
  410.             month is in the range [1...12]
  411.             mday is in the range [1...31]
  412.             yday is in the range [0...365]
  413.  
  414.     OUTPUT
  415.         In case of error...
  416.  
  417.         The input data.
  418.         The Julian day calculated from the date by juldn.
  419.         The year, month, day, weekday, and day of year (0...365)
  420.         calculated from the Julian day by julcd.
  421.  
  422.         Outputs that don't match the corresponding inputs are marked with '*'.
  423.  
  424.            JD              date            juldn(date)           julcd(JD)
  425.         -------     ------------------     -----------     --------------------
  426.         2430336     1941 12  7 Sun 340       2430336       1941 12  7  Sun  340  
  427.  
  428.         There are also three sets of random tests.  Again, '*'
  429.         indicates a disagreement.
  430.  
  431.         The first set is for self consistency: two dates, ten days
  432.         apart, should result in Julian dates that differ by ten.
  433.  
  434.         The second set compares the normalization of dates as found by
  435.         mktime and juldn.  Due to buggy implementations of mktime
  436.         (Borland, Sun), in case of a disagreement the test program
  437.         tries to identify which function is incorrect.  First, it
  438.         adjusts the month and compensates with the year.  If the two
  439.         functions then agree, it prints their results.  Otherwise, it
  440.         looks for a boundary between agreement and disagreement.  It
  441.         then prints results for dates on each side of the boundary.  In
  442.         either case, comparing the last two lines should show which
  443.         function is incorrect.
  444.  
  445.         The third set compares tm_wday and tm_yday as found by julcd(),
  446.         juldn(), and gmtime().
  447.  
  448. */
  449. #include <stdio.h>
  450. #include <string.h>
  451. #include <time.h>
  452. #include "julcal.h"
  453.  
  454. #define BUFSIZE 200
  455.  
  456. char buf[BUFSIZE+1];
  457. FILE *ifile;
  458. char *filename = "data";
  459. #define streq(a,b) (strcmp(a,b)==0)
  460.  
  461. main(argc, argv) int argc; char **argv;
  462. {    char *s, tdayname[4];
  463.     static char *weekdayname[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  464.     static char item1_heading[]=
  465. "    JD              date            juldn(date)           julcd(JD)\n\
  466.  -------     ------------------     -----------     --------------------\n";
  467.     static char item2_heading[]=
  468. "\n\
  469.      before                 after\n\
  470. --------------    --------------------------\n\
  471. year month day    year month day  Julian day\n";
  472. #ifdef MKTIME
  473.     static char item3_heading[]=
  474. "\n\
  475.      before           mktime             juldn\n\
  476. --------------    --------------    --------------\n";
  477.     int item3=0;
  478. #endif
  479.     static char item4_heading[]=
  480. "\n\
  481.                        gmtime               julcd           juldn\n\
  482.                ----------------------     ----------     ----------\n\
  483.    time_t         date     wday  yday     wday  yday     wday  yday\n";
  484. /*   xxxxxxxxxx -> 4444/22/22 -> 1    333      1    333 */
  485.     int item4=0;
  486.  
  487.     int fields, same_jd, same_date, i;
  488.     int verbose=0, item1=0, item2=0;
  489.     long tjd; struct tm tbdt;    /* test data, from file */
  490.     long rjd; struct tm rbdt;    /* results, from functions */
  491.     long j0, j10;
  492.     int tyear, ryear, dy, dd, error;
  493.     time_t when;
  494.     struct tm *bdt1, *bdt2;
  495.     struct tm before, before0, before10, after0, after10, theirs, ours;
  496.  
  497.     for (i = 1; i < argc; i++)
  498.         {if(streq(argv[i],"-v")) verbose=1;
  499.         else filename = argv[i];
  500.         }
  501.  
  502.     ifile = fopen(filename, "r");
  503.     if(ifile == 0) {fprintf(stderr, "can't open file %s\n", filename); exit(1);}
  504.  
  505.     while(fgets(buf, BUFSIZE, ifile))
  506.         {
  507.         if(s = strchr(buf, '\n')) *s = 0;    /* zap LF */
  508.         if(buf[0] == ';') 
  509.             {
  510.             if(verbose) printf("%s\n", buf);  /* echo cmt line */
  511.             continue;
  512.             }
  513.         if(buf[0] == 'T')
  514.             {    /* set new default transition date */
  515.             sscanf(buf, "T%ld", &jul_transition);
  516.             if(verbose) printf("%s\n", buf);
  517.             continue;
  518.             }
  519.         if(s = strchr(buf, ';')) *s = 0;    /* zap trailing comment */
  520.         tbdt.tm_year = 0;
  521.         tbdt.tm_mon = 0;
  522.         tbdt.tm_mday = 1;
  523.         tbdt.tm_wday = 1;
  524.         fields = sscanf(buf, "%ld %d %d %d %3s %d", &tjd, &tbdt.tm_year,
  525.             &tbdt.tm_mon, &tbdt.tm_mday, &tdayname, &tbdt.tm_yday);
  526.         if(fields < 1) continue;
  527.         for (i = 0; i < 7; i++)
  528.             if(streq(tdayname, weekdayname[i]))
  529.                 break;
  530.         tbdt.tm_wday = i; 
  531.  
  532.                     /* adjust for struct_tm offsets */
  533.         if(tbdt.tm_year < 0) tbdt.tm_year -= 1899;
  534.         else tbdt.tm_year -= 1900;
  535.         tbdt.tm_mon--;
  536.  
  537.         rjd = juldn(&tbdt);
  538.         rbdt = *julcd(tjd);
  539.  
  540.         same_date = (rbdt.tm_year == tbdt.tm_year)
  541.                 && (rbdt.tm_mon == tbdt.tm_mon)
  542.                 && (rbdt.tm_mday == tbdt.tm_mday)
  543.                 && (rbdt.tm_wday == tbdt.tm_wday)
  544.                 && (rbdt.tm_yday == tbdt.tm_yday);
  545.         same_jd = (rjd == tjd);
  546.         if(verbose || !same_jd || !same_date)
  547.             {
  548.             if(!item1) printf(item1_heading);
  549.             item1 = 1;
  550.             tyear = tbdt.tm_year + 1900; if(tyear < 1) tyear--;
  551.             ryear = rbdt.tm_year + 1900; if(ryear < 1) ryear--;
  552.             printf("%8ld    %5d %2d %2d %3s %3d       %7ld %s    %5d %2d %2d  %s  %3d %s\n",
  553.                 tjd, tyear, tbdt.tm_mon+1, tbdt.tm_mday, tdayname, tbdt.tm_yday,
  554.                 rjd, same_jd?" ":"*", 
  555.                 ryear, rbdt.tm_mon+1, rbdt.tm_mday,
  556.                 weekdayname[rbdt.tm_wday], rbdt.tm_yday, 
  557.                 same_date?" ":"*");
  558.             }
  559.         }
  560.  
  561. /*
  562.     Check normalization (correction for day or month out of the normal
  563.     range) of juldnj.
  564.  
  565. */
  566.     for (i = 0; i < 5000; i++)
  567.         {    /* test period is 1780 - 5 - 1 ... 1780 + 700 + 5 + 1
  568.                         or 1774 ... 2486 
  569.                 (after transition to Gregorian calendar) */
  570.         before0.tm_year = 1780 - 1900 + rand()%700;
  571.         before0.tm_mon = -60 + rand()%120;
  572.         before0.tm_mday = -360 + rand()%720;
  573.         before0.tm_sec = before0.tm_min = before0.tm_hour = 0;
  574.         before10 = before0;
  575.         dy = rand()%14;
  576.         before10.tm_year -= dy;
  577.         before10.tm_mon += dy*12;
  578.         before10.tm_mday += 10;
  579.                 /* 'before10' now has a date 10 days later than 'before0' */
  580.  
  581.         after0 = before0;
  582.         after10 = before10;
  583.         j0 = juldn(&after0);
  584.         j10 = juldn(&after10);
  585.  
  586.                 /* check that final dates are normalized & 10 days apart */
  587.         error =    j10 != j0 + 10 
  588.             || after0.tm_mon < 0
  589.             || after0.tm_mon > 11
  590.             || after0.tm_mday < 1
  591.             || after0.tm_mday > 31
  592.             || after10.tm_mon < 0
  593.             || after10.tm_mon > 11
  594.             || after10.tm_mday < 1
  595.             || after10.tm_mday > 31
  596.             || ((after0.tm_mon == after10.tm_mon)?
  597.                 (after10.tm_mday != after0.tm_mday + 10)
  598.                 : ((after0.tm_mon + 1)%12 != after10.tm_mon
  599.                     || after0.tm_mday - after10.tm_mday + 10 > 31
  600.                     || after0.tm_mday - after10.tm_mday + 10 < 28));
  601.         if((verbose && i < 10) || error)
  602.             {
  603.             if(!item2) printf(item2_heading); 
  604.             printf("%4d %4d %4d -> %4d %4d %4d = JD%ld\n", 
  605.                 before0.tm_year+1900, before0.tm_mon+1, before0.tm_mday,
  606.                 after0.tm_year+1900, after0.tm_mon+1, after0.tm_mday, j0);
  607.             printf("%4d %4d %4d -> %4d %4d %4d = JD%ld\n\n", 
  608.                 before10.tm_year+1900, before10.tm_mon+1, before10.tm_mday,
  609.                 after10.tm_year+1900, after10.tm_mon+1, after10.tm_mday, j10);
  610.             if(++item2 > 15) break;
  611.             }
  612.         }
  613.  
  614. #ifdef MKTIME
  615. /*
  616.     Compare normalization (correction for day or month out of the
  617.     normal range) of juldnj with mktime().  
  618.  
  619. */
  620.     for (i = 0; i < 5000; i++)
  621.         {
  622.         before.tm_year = 1980 - 1900 + rand()%30;
  623.         before.tm_mon = -60 + rand()%120;
  624.         before.tm_mday = -200 + rand()%400;
  625.         before.tm_sec = before.tm_min = 0;
  626.         before.tm_hour = 0;
  627.         error = make_comparison(&before, &theirs, &ours);
  628.         if((verbose && i < 10) || error)
  629.             {
  630.             if(!item3) printf(item3_heading);
  631.             print_comparison(&before, &theirs, &ours, error);
  632.             if(error)
  633.                 {
  634.                 dy = before.tm_mon/12;
  635.                 if(before.tm_mon < 0) dy--;
  636.                 before.tm_mon -= dy*12;
  637.                 before.tm_year += dy;
  638.                 error = make_comparison(&before, &theirs, &ours);
  639.                 if(!error) print_comparison(&before, &theirs, &ours, error);
  640.                 else
  641.                     {
  642.                     dd = before.tm_mday>0 ? 1 : -1;
  643.                     for (i = 0; i < 250; i++)
  644.                         {
  645.                         before.tm_mday -= dd;
  646.                         error = make_comparison(&before, &theirs, &ours);
  647.                         if(!error) 
  648.                             {
  649.                             before.tm_mday += dd;
  650.                             error = make_comparison(&before, &theirs, &ours);
  651.                             print_comparison(&before, &theirs, &ours, error);
  652.                             before.tm_mday -= dd;
  653.                             break;
  654.                             }
  655.                         }
  656.                     error = make_comparison(&before, &theirs, &ours);
  657.                     print_comparison(&before, &theirs, &ours, error);
  658.                     }
  659.                 printf("\n");
  660.                 }
  661.             if(++item3 > 15) break;
  662.             }
  663.         }
  664. #endif /* MKTIME */
  665.  
  666. /*
  667.     Compare calculation of tm_wday and tm_yday with gmtime().  (All these
  668.     are after 1 Jan 1970, so necessarily A.D. and for Gregorian calendar.)
  669. */
  670.     for (i = 0; i < 5000; i++)    /* this takes ~5 sec on a 25 MHz 386 */
  671.         {
  672.         when = (((long)rand())<<16) + rand();
  673.         bdt1 = gmtime(&when);
  674.         ours = *bdt1;
  675.         bdt2 = julcd(juldn(&ours)); /* both ours and *bdt2 get wday and yday */
  676.         error =    bdt1->tm_wday != bdt2->tm_wday 
  677.             || bdt1->tm_yday != bdt2->tm_yday
  678.             || bdt1->tm_wday != ours.tm_wday 
  679.             || bdt1->tm_yday != ours.tm_yday;
  680.         if((verbose && i < 10) || error)
  681.             {
  682.             if(!item4) printf(item4_heading);
  683.             printf("%11ld -> %4d/%02d/%02d    %d    %3d       %d    %3d",
  684.                 when, 
  685.                 bdt1->tm_year+1900, bdt1->tm_mon+1, bdt1->tm_mday,
  686.                 bdt1->tm_wday, bdt1->tm_yday, 
  687.                 bdt2->tm_wday, bdt2->tm_yday);
  688.             printf("       %d    %3d %s\n",
  689.                 ours.tm_wday, ours.tm_yday,
  690.                 error?"*":" ");
  691.             if(++item4 > 15) break;
  692.             }
  693.         }
  694. }
  695.  
  696. make_comparison(before, theirs, ours)
  697.     struct tm *before, *theirs, *ours;
  698. {        *ours = *theirs = *before;
  699.         juldn(ours);
  700.         mktime(theirs);
  701.         return ours->tm_year != theirs->tm_year
  702.             || ours->tm_mon != theirs->tm_mon
  703.             || ours->tm_mday != theirs->tm_mday;
  704. }
  705.  
  706. print_comparison(before, theirs, ours, error)    
  707.     struct tm *before, *theirs, *ours; int error;
  708. {
  709.             printf("%4d %4d %4d -> %4d %4d %4d    %4d %4d %4d %s\n", 
  710.                 before->tm_year+1900, before->tm_mon+1, before->tm_mday,
  711.                 theirs->tm_year+1900, theirs->tm_mon+1, theirs->tm_mday,
  712.                 ours->tm_year+1900, ours->tm_mon+1, ours->tm_mday,
  713.                 error?"*":" ");
  714. }
  715. SHAR_EOF
  716. cat << \SHAR_EOF > dates.txt
  717.  
  718. Article 58087 (1228 more) in comp.lang.c:
  719.  
  720. Subject: Re: algorithm for day-of-week
  721. From: comjohn@ccu1.aukuni.ac.nz (Mr. John T Jensen)
  722. Date: Tue, 20 Oct 1992 02:33:01 GMT
  723. Distribution: comp
  724.  
  725. There is a very nice article with algorithms for this and other calendrical
  726. problems that I can recommend:
  727.  
  728. Calendrical Calculations, by Nachum Dershowitz and Edward M. Reingold.  In
  729. Software-Practice and Experience, Vol. 20, number 9 (September 1990), pp
  730. 899-928.
  731.  
  732. jj
  733.  
  734. John Thayer Jensen                      64 9 373 7599 ext. 7543
  735. Commerce Computer Services              64 9 373 7437 (FAX)
  736. Auckland University                     jt.jensen@aukuni.ac.nz
  737. Private Bag 92019
  738. AUCKLAND
  739. New Zealand
  740.  
  741.  
  742.  
  743.  
  744.  
  745. Article 58154 (1197 more) in comp.lang.c:
  746. From: msb@sq.sq.com (Mark Brader)
  747.  
  748. Subject: Re: ******* DATES *********
  749. Date: Wed, 21 Oct 92 07:00:56 GMT
  750.  
  751. > This is probably in the FAQ, but I'm feeling a rebel today.
  752.  
  753. No, it isn't, but do you know, I think it should be.  It certainly is
  754. not a C question, but it *does* seem to be Frequently Asked in this
  755. newsgroup anyway!
  756.  
  757. > What was the final word in the leap year arguments?
  758.  
  759. The final word is irrelevant, since article sequence is random and every
  760. post on the topic attracts a slew of fresh responses from people anxious
  761. to display their ignorance on a worldwide network.  Now, if you want the
  762. *correct* answer...
  763.  
  764. > Is 2000 a leap year?
  765.  
  766. Yes.
  767.  
  768. > Is it a single or double-exception year?
  769.  
  770. Well, I'd call it a triple exception.  Depends on how you count.
  771. Year y is a leap year if and only if:
  772.  
  773.     (y % 4 == 0 && y % 100 != 0)  ||  y % 400 == 0
  774.  
  775. (The parentheses are redundant, of course, but included for clarity.)
  776.  
  777. Since some people seem to have trouble believing that this is right,
  778. here's some supporting evidence, taken from the reference book most
  779. conveniently to hand, the 1989 Information Please Almanac (p549-550):
  780.  
  781. #  For long-range accuracy, a formula suggested by the Vatican
  782. #  librarian Aloysius Giglio (Latinized into Lilius) was adopted:
  783. #  every fourth year is a leap year UNLESS it is a century year
  784. #  like 1700 or 1800.  Century years can be leap years ONLY when
  785. #  they are divisible by 400 (e.g. 1600).  This rule eliminates
  786. #  three leap years in four centuries, making the calendar suf-
  787. #  ficiently correct for all ordinary purposes.
  788. #  
  789. #  ... The average year of the Gregorian calendar [i.e. the one
  790. #  just described], in spite of the leap year rule, is about 26
  791. #  seconds longer than the earth's orbital period.  But this
  792. #  discrepancy will need 3,323 years to build up to a single day.
  793. #  
  794. #  Modern proposals for calendar reform do not aim at a "better"
  795. #  calendar, but at one that is more convenient to use, especially
  796. #  for commercial purposes. ...
  797.  
  798. I also have online a copy of the British law of 1751 decreeing
  799. the adoption (the following year) of the Gregorian calendar
  800. "in and throughout all his Majesty's Dominions and Countries
  801. in Europe, Asia, Africa and America, belonging or subject to
  802. the Crown of Great Britain"; and it specifies the same rule.
  803. (I'll email this text to anyone who asks, but be warned that
  804. it's several pages long and entirely in language like that.)
  805. And yes, it specifies the same rule.
  806.  
  807. According to past postings in sci.astro, which is probably the
  808. best group for this topic, a small minority of references claim
  809. that there is one more level of exception which has been adopted;
  810. but posters who would be in a position to know about this have
  811. said that it was wrong.  It would not make sense anyway, because
  812. the length of the year is not sufficiently constant over millenia.
  813.  
  814. > Is there a reliable, simple function around to calculate this?
  815. > I cannot use C, I'm building something in a 4GL and I have to
  816. > count days back to, well, a long time ago.
  817.  
  818. Well, if it's a *long* time ago, you may get into issues of when the
  819. country in question *changed* to the Gregorian calendar.  That could
  820. be anywhere from the 16th to the 20th century.  Then there is the
  821. matter of the year not always having begun on January 1...
  822.  
  823. > "This must be Thursday.  I never could get the hang of Thursdays"
  824.  
  825. Nice choice of quote.
  826. -- 
  827. Mark Brader, Toronto    "If the standard says that [things] depend on the
  828. utzoo!sq!msb         phase of the moon, the programmer should be prepared
  829. msb@sq.com         to look out the window as necessary."  -- Chris Torek
  830.  
  831. This article is in the public domain.
  832.  
  833.  
  834. Article 58195 (1195 more) in comp.lang.c:
  835. From: bob@black.ox.ac.uk (Bob Douglas)
  836.  
  837. Subject: Re: ******* DATES *********
  838. Date: 21 Oct 92 18:34:43 GMT
  839. Originator: bob@black
  840.  
  841. In article <exuptr.772.719596858@exu.ericsson.se> exuptr@exu.ericsson.se (Patric
  842. k Taylor) writes:
  843.  
  844. >This is probably in the FAQ, but I'm feeling a rebel today.
  845. >
  846. >What was the final word in the leap year arguments?  Is 2000 a leap year?
  847. >Is it a single or double-exception year?
  848. >
  849. >Is there a reliable, simple function around to calculate this?  I cannot use
  850. >C, I'm building something in a 4GL and I have to count days back to, well, 
  851. >a long time ago.
  852.  
  853. If you don't want to go back too far (say not before 1800) you can use
  854. just the Gregorian calendar whose rules are simple:
  855.  
  856.     A year
  857.  
  858.         - is a leap year if it is divisible by 400; otherwise
  859.  
  860.         - it is not a leap year if it is divisible by 100; otherwise
  861.  
  862.         - it is a leap year if it is divisible by 4; otherwise
  863.  
  864.         - it is not a leap year
  865.  
  866.     As a C statement we have
  867.  
  868.         leap = (year % 400 == 0) ||
  869.                (year % 100 != 0 && year % 4 == 0)
  870.  
  871. However, if you want to go back much further than 1800, you may have to
  872. use the Julian calendar, when things can get more complicated:
  873.  
  874.     - there are two formulae to consider (Julian and Gregorian)
  875.  
  876.     - you have to fix a date at which to start the Gregorian calendar.
  877.       With historical dates this can depend on where dates for
  878.       consideration arise
  879.  
  880.     - you may have to make adjustments to historical dates for
  881.       places and years which do not start on 1 January
  882.  
  883. If this is the case, read the material below. And good luck.
  884.  
  885. Bob Douglas
  886.  
  887. ===========================================================================
  888.  
  889.                   Julian/Gregorian Calendar Changeover
  890.                   ====================================
  891.  
  892. The Julian calendar was devised at the instigation of Julius Caesar and
  893. come into use in 45 BC or 709 AUC although confusion reigned during its
  894. first fifty or so years. It finally stabilized in 8 AD or 761 AUC. The
  895. Julian calendar has just one rule
  896.  
  897.     (1) Every fourth year is a leap year. The first leap year was
  898.         45 BC, so 1 BC was a leap year and hence so was 4 AD (there
  899.         being no year zero: 1 BC is followed by 1 AD). Hence for years
  900.         AD, if the year is divisible by 4, it is a leap year
  901.  
  902. Thus the Julian calendar assumes a year of exactly 365.25 days.
  903.  
  904. In fact the mean tropical year (used for fixing the seasons) is 365.242199
  905. days, which means that the Julian year is about 11 minutes 14 seconds too
  906. long, an error which grows to about a day in 133 years. Thus in 400 Julian
  907. years there are about 3 days too many.
  908.  
  909. Hence in the sixteenth century Pope Gregory XIII authorized a revision of
  910. the calendar, and decreed that
  911.  
  912.    (1) Centennial years should in future no longer be leap years
  913.        unless they were divisible by 400 (i.e. 1600, 2000, 2400
  914.        are leap years; 1700, 1800, 1900 are not). Non-centennial
  915.        years should continue to be leap years if they are
  916.        divisible by 4.
  917.  
  918.    (2) Thursday 4 October 1582 (Julian calendar) would be followed
  919.        by Friday 15 October 1582 (Gregorian calendar). The gap of
  920.        10 days corrected the accumulated error in the Julian
  921.        calendar.
  922.  
  923. Thus the Gregorian calendar assumes a year of exactly 365.2425 days,
  924. so it is about 26 seconds too long. This error will grow to a day in
  925. about 3300 years, so we can safely leave future calendar corrections
  926. to a (far) future generation.
  927.  
  928. Note: AUC - Ab urbe condita
  929.             From the (traditional) founding of the city (of Rome) - 753 BC
  930.  
  931. ==========================================================================
  932.  
  933. The above rules should make the decision about a year being a leap year
  934. an easy one:
  935.  
  936.     Using the Gregorian calendar, a year (1 AD or later):
  937.  
  938.         - is a leap year if it is divisible by 400; otherwise
  939.  
  940.         - it is not a leap year if it is divisible by 100; otherwise
  941.  
  942.         - it is a leap year if it is divisible by 4; otherwise
  943.  
  944.         - it is not a leap year
  945.  
  946.     Using the Julian calendar:
  947.  
  948.         - a positive year (AD) is a leap year if it is divisible by 4
  949.  
  950.         - a negative year (BC) is a leap year if its absolute value
  951.           less 1 is divisible by 4
  952.  
  953.     As C statements we have
  954.  
  955.         Gregorian:   leap = (year % 400 == 0) ||
  956.                                (year % 100 != 0 && year % 4 == 0)
  957.  
  958.         Julian:      leap = (year > 0 ? year % 4 == 0 : (-year-1) % 4 == 0)
  959.  
  960. ==========================================================================
  961.  
  962.     However, we are still not quite home and dry. To add to the confusion,
  963.     the first day of the year has varied through the ages.
  964.  
  965.     In early Rome March was the first month of the year (hence SEPTember,
  966.     OCTober, NOVember, DECember - months 7, 8, 9, 10); but in 153 BC,
  967.     when consuls started entering office on 1 January, this became the
  968.     first day of the official year.
  969.  
  970.     In Western Europe, in the Christian era, 1 January was gradually
  971.     adopted as the first day of the year, but different places did
  972.     this at widely different dates, and before this standardization
  973.     there were several different starts to the year. For example
  974.  
  975.         (1) Italy, down to the 18-th century
  976.  
  977.                 The Venetian new year started on the following 1 March
  978.                 The Pisan new year started on the preceding 25 March
  979.                 The Florentine new year started on the following 25 March
  980.                 In Rome various new years were used for different purposes
  981.  
  982.         (2) In England during the 14-th century the new year gradually
  983.             changed from the preceding 25 December to the following
  984.             25 March. Then, by the Act that established the Gregorian
  985.             calendar, from 1753 the new year started on 1 January
  986.  
  987.         (3) Scotland (independent from England until the Act of Union
  988.             in 1707) established 1 January as the first day of the year
  989.             from 1600.
  990.  
  991. It is safe, I think, to asusme that all Gregorian calendar years start
  992. on 1 January.
  993.  
  994. However, the effect of years that do not start on 1 January can be to
  995. upset the calculation of a (Julian) leap year. For example, if years
  996. start on the following 25 March (as for a long time they did in England),
  997. then the day before 1 March 1664 is 29 February 1663 (what we should call
  998. 29 February 1664). Thus the year which started on 1 March 1663 is a leap
  999. year although 1663 is not divisible by 4.
  1000.  
  1001. This problem can be avoided by regarding years as starting always on
  1002. 1 January, of course, but when dealing with historical dates the
  1003. conversion to a 1 January year start depends on knowledge of the year
  1004. start locally in use at that date:
  1005.  
  1006.     With a Pisan year 1 June 1588 becomes 1 June 1587
  1007.     With a Florentine year 1 June 1588 stays 1 June 1588
  1008.  
  1009.     With a Pisan year 1 February 1588 stays 1 February 1588
  1010.     With a Florentine year 1 February 1588 becomes 1 February 1589
  1011.  
  1012. ==========================================================================
  1013.  
  1014. By and large, Catholic countries adopted the Gregorian calendar at or
  1015. about the time Gregory's edict stated. Protestant countries didn't;
  1016. but sooner or later they had to conform as their calendars were getting
  1017. more and more out of step with the seasons as the centuries passed.
  1018.  
  1019. Below are (sometimes approximate) dates of calendar conversion for
  1020. many countries. Surprisingly, there seems to be considerable doubt
  1021. over when some areas changed. Information below is taken from
  1022.  
  1023.       Explanatory Supplement to the Astronomical Ephemeris
  1024.       and the American Ephemeris and Nautical Almanac
  1025.  
  1026.       Her Majesty's Stationary Office, London, 1961
  1027.  
  1028. This gives several other references, mainly obscure German works.
  1029.  
  1030. Where it is known exactly, the changeover is given in the form
  1031.  
  1032.       last Julian date - first Gregorian date
  1033.  
  1034. otherwise approximate dates (usually just years) are given.
  1035.  
  1036. [I have added the Julian Day Number in square brackets for the first
  1037. Gregorian date, assuming Jan 1 where only the year is given 
  1038. - Jim Van Zandt<jrv@mitre.org>]
  1039.  
  1040. Remember that many European countries had very different borders at the
  1041. time of the changeover to those they have now (e.g. Poland, Hungary).
  1042. There have been changes in political authority too. The German states
  1043. particularly formed just a linguistic area comprising (roughly) modern
  1044. Austria, Germany, Czechoslovakia and Switzerland; and different political
  1045. entities (and sometimes even the ecclesiastical and civil authorities in
  1046. one area) adopted the Gregorian calendar at different dates. See the
  1047. above reference for more details.
  1048.  
  1049. ==========================================================================
  1050.  
  1051. Alaska                             Gregorian calendar adopted when the USA
  1052.                                    bought Alaska from Russia (18 October 1867)
  1053.  
  1054. Albania                            December 1912
  1055.  
  1056. American Colonies                  See Great Britain
  1057.  
  1058. Austria                            Different regions on different dates
  1059.                                         6 Oct 1583 - 16 Oct 1583 [JD2299527]
  1060.                                        15 Dec 1583 - 25 Dec 1583 [JD2299597]
  1061.  
  1062. Belgium                            Different authorities say
  1063.                                        15 Dec 1582 - 25 Dec 1582 [JD2299232]
  1064.                                        22 Dec 1582 -  1 Jan 1583 [JD2299239]
  1065.  
  1066. Bulgaria                           Different authorities say
  1067.                                        Sometime in 1912 [JD2419403]
  1068.                                        19 Mar 1916 -  1 Apr 1916 [JD2420955]
  1069.  
  1070. China                              Different authorities say
  1071.                                        19 Dec 1911 -  1 Jan 1912 [JD2419403]
  1072.                                        19 Dec 1928 -  1 Jan 1929 [JD2425613]
  1073.  
  1074. Czechoslovakia (i.e. Bohemia and Moravia)
  1075.                     7 Jan 1584 - 17 Jan 1584 [JD2299620]
  1076.  
  1077. Denmark (including Norway)         19 Feb 1700 - 1 Mar 1700 [JD2342032]
  1078.  
  1079. Egypt                              1875 [JD2405890]
  1080.  
  1081. Estonia                            January 1918 [JD2421595]
  1082.  
  1083. Finland                            Then part of Sweden (q.v.)
  1084.  
  1085. France                             10 Dec 1582 - 20 Dec 1582 [JD2299227]
  1086.  
  1087. German States                      Different states on different dates:
  1088.                                        14 Feb 1583 - 24 Feb 1583 [JD2299293]
  1089.                                         5 Oct 1583 - 15 Oct 1583 [JD2299526]
  1090.                                         6 Oct 1583 - 16 Oct 1583 [JD2299527]
  1091.                                         3 Nov 1583 - 13 Nov 1583 [JD2299555]
  1092.                                         4 Nov 1583 - 14 Nov 1583 [JD2299556]
  1093.                                         5 Nov 1583 - 15 Nov 1583 [JD2299557]
  1094.                                        12 Nov 1583 - 22 Nov 1583 [JD2299564]
  1095.                                        17 Nov 1583 - 27 Nov 1583 [JD2299569]
  1096.                                         7 Jan 1584 - 17 Jan 1584 [JD2299620]
  1097.                                        13 Jan 1584 - 23 Jan 1584 [JD2299626]
  1098.                                         2 Jul 1584 - 12 Jul 1584 [JD2299797]
  1099.                                        17 Jun 1585 - 27 Jun 1585 [JD2300147]
  1100.                                        23 Aug 1610 -  2 Sep 1610   (a) [JD2309345]
  1101.                                        14 Dec 1615 - 24 Dec 1615 [JD2311284]
  1102.                                        16 Mar 1631 - 26 Mar 1631 [JD2316855]
  1103.                                        19 Feb 1700 -  1 Mar 1700   (b) [JD2342032]
  1104.                                    Note:
  1105.                                    (a) Prussia
  1106.                                    (b) Protestant Germany
  1107.  
  1108. Great Britain and Dominions         3 Sep 1752 - 14 Sep 1752 [JD2361222]
  1109.  
  1110. Greece                             10 Mar 1924 - 23 Mar 1924 [JD2423868]
  1111.  
  1112. Hungary                            22 Oct 1587 -  1 Nov 1587 [JD2301004]
  1113.  
  1114. Italy                               5 Oct 1582 - 15 Oct 1582 [JD2299161]
  1115.  
  1116. Japan                              19 Dec 1918 -  1 Jan 1919 [JD2421960]
  1117.  
  1118. Latvia                             During German occupation 1915 to 1918 [1/1/1915->JD2420499]
  1119.  
  1120. Lithuania                          1915 [JD2420499]
  1121.  
  1122. Luxemburg                          15 Dec 1582 - 25 Dec 1582 [JD2299232]
  1123.  
  1124. Netherlands                        Catholic:    various 1582 or 1583 [10/15/1582->JD2299161]
  1125.                                    Protestant:  various 1700 or 1701 [1/1/1700->JD2341973]
  1126.  
  1127. Norway                             Then under Danish rule. See Denmark
  1128.  
  1129. Poland                              5 Oct 1582 - 15 Oct 1582 [JD2299161]
  1130.  
  1131. Portugal                            5 Oct 1582 - 15 Oct 1582 [JD2299161]
  1132.  
  1133. Romania                             1 Apr 1919 - 14 Apr 1919 [JD2422063]
  1134.  
  1135. Spain                               5 Oct 1582 - 15 Oct 1882 [JD2408734]
  1136.  
  1137. Sweden (including Finland)         18 Feb 1753 - 1 Mar 1753 [JD2361390]
  1138.  
  1139. Switzerland                        Varied with the Cantons. Generally one of
  1140.                                        12 Jan 1584 - 22 Jan 1584 [JD2299625]
  1141.                                         1 Jan 1701 - 12 Jan 1701 [JD2342349]
  1142.  
  1143. Turkey                             19 Dec 1926 -  1 Jan 1927 [JD2424882]
  1144.  
  1145. Yugoslavia (as it then was)        1919 [JD2421960]
  1146.  
  1147. UK                                 See Great Britain
  1148.  
  1149. USA (then American colonies)       See Great Britain
  1150.  
  1151. USSR (as it then was)               1 Feb 1918 - 14 Feb 1918 [JD2421639]
  1152. -- 
  1153. Bob Douglas              Computing Services, University of Oxford
  1154. Internet:                bob@oxford.ac.uk
  1155. Address:                 13 Banbury Road, Oxford OX2 6NN, UK
  1156. Telephone:               +44-865-273211
  1157.  
  1158.  
  1159. Article 58330 (1192 more) in comp.lang.c:
  1160. From: bob@black.ox.ac.uk (Bob Douglas)
  1161.  
  1162. Subject: Re: ******* DATES *********
  1163. Date: 23 Oct 92 13:31:12 GMT
  1164. Originator: bob@black
  1165.  
  1166. In article <BwJGJw.Fn3@sci.kun.nl> hansm@cs.kun.nl (Hans Mulder) writes:
  1167. >In <1992Oct21.183443.27418@black.ox.ac.uk> bob@black.ox.ac.uk (Bob Douglas) wri
  1168. tes:
  1169. >
  1170. >>Hence in the sixteenth century Pope Gregory XIII authorized a revision of
  1171. >>the calendar, and decreed that
  1172. >
  1173. >>   (1) Centennial years should in future no longer be leap years
  1174. >>       unless they were divisible by 400 (i.e. 1600, 2000, 2400
  1175. >>       are leap years; 1700, 1800, 1900 are not). Non-centennial
  1176. >>       years should continue to be leap years if they are
  1177. >>       divisible by 4.
  1178. >
  1179. >>   (2) Thursday 4 October 1582 (Julian calendar) would be followed
  1180. >>       by Friday 15 October 1582 (Gregorian calendar). The gap of
  1181. >>       10 days corrected the accumulated error in the Julian
  1182. >>       calendar.
  1183. >
  1184. >Errhm, I would think that the accumulated error was 12 day: the years
  1185. >100, 200, 300, 500, 600, 700, 900, 1000, 1100, 1300, 1400 and 1500 had
  1186. >been leap years, and under the new rules they shouldn't have been.
  1187. >
  1188. >Does anybody know why Gregory XIII skipped only 10 days?
  1189. >
  1190. >--
  1191. >Puzzled,
  1192. >
  1193. >Hans Mulder            hansm@cs.kun.nl
  1194.  
  1195. I (who posted the above article) noticed this too. The Gregorian
  1196. amendment to the Julian calendar is such that, if the Gregorian
  1197. calendar is extrapolated backwards, the two calendars are in
  1198. agreement in the third century (from 1 March 200 to 28 February 300)
  1199. instead of in the first century (from 1 January 1 AD) when the
  1200. Julian calendar was two days ahead of the Gregorian one (it is now
  1201. 13 days behind). Why this is so I do not know.
  1202.  
  1203. The Gregorian calendar was devised by Christopher Clavius (a 16-th
  1204. century mathematician and astronomer) on instruction from Pope
  1205. Gregory XIII. The ultimate reference to the design must be
  1206.  
  1207. Christopher Clavius.
  1208. Kalendarium Perpetuum. Cum Privilegio Summi Pontificis Et Aliorum Principum.
  1209. Rome, Ex Officina Dominicae Basae. MDLXXXII. Cum Licentia Superiorum
  1210.  
  1211. However, none of the British Library, The Bibliotheque National or the
  1212. Library of Congress have copies. No doubt one is to be found in the Vatican
  1213. archives.
  1214.  
  1215. But all is not lost! An explanatory volume was also prepared (c.f. the
  1216. ANSI C Rationale) also by Christopher Clavius:
  1217.  
  1218. Romani Calendarii a Gregorio XIII. Pontifice Maximo Restituti Explicato.
  1219. Rome, 1603
  1220.  
  1221. Copies of this are available in the British Library and the Bibliotheque
  1222. Nationale (but not the Library of Congress). And no, I haven't read it!!
  1223.  
  1224. -- 
  1225. Bob Douglas              Computing Services, University of Oxford
  1226. Internet:                bob@oxford.ac.uk
  1227. Address:                 13 Banbury Road, Oxford OX2 6NN, UK
  1228. Telephone:               +44-865-273211
  1229.  
  1230.  
  1231. Article 58338 (1191 more) in comp.lang.c:
  1232. From: msb@sq.sq.com (Mark Brader)
  1233.  
  1234. Subject: Re: ******* DATES *********
  1235. Date: Fri, 23 Oct 92 16:43:59 GMT
  1236.  
  1237. This thread *really* should be elsewhere, such as sci.astro or soc.history,
  1238. but I'm not going to be the one to redirect it.
  1239.  
  1240. In a nice table of Julian/Gregorian dates, Bob Douglas (bob@black.ox.ac.uk)
  1241. writes:
  1242.  
  1243. > Sweden (including Finland)         18 Feb 1753 - 1 Mar 1753
  1244.  
  1245. This is correct, but is only part of the story.  As Anders Berglund wrote
  1246. back in 1986 in the newsgroup net.bugs, in Sweden they had the marvelous idea
  1247.  
  1248. | ... to gradually adapt to the Gregorian style by dropping all leap
  1249. | days, starting with the year 1700!  Since this would bring us ONE day
  1250. | closer for every fourth year it also would mean that Sweden was to have
  1251. | a unique calendar for the FORTY years it would take to overbridge this
  1252. | ten-day time slip!!  Truly a solution of the "splendid isolation" type!
  1253. |  
  1254. | However, it didn't work out that way.  The king was away on endless
  1255. | war-tours in Russia and the government at home neglected to fulfill
  1256. | the plan (if there was a reason, I don't know it).  So, when 1704 came
  1257. | along they happily enjoyed their leap day, and the same happened in
  1258. | 1708.  When 1712 was in sight someone obviously had got tired of this
  1259. | one-day-ahead-or-ten-days-after style.  It was decided to make an end
  1260. | to it by -- listen to this! -- going BACK to Julian style!
  1261. |  
  1262. | This is why Sweden got two leap days in 1712, making a 30-day February! 
  1263. | Is there anything like this on record in any other coutry...?
  1264.  
  1265. I should mention that there is at least one book in English (called
  1266. "Winning Ways") which mentions this story and gets it wrong.  The topic
  1267. arose on rec.puzzles a while back and the above story was verified from
  1268. Swedish sources.
  1269.  
  1270. Finland was part of the territory that Sweden and Russia were fighting over,
  1271. I understand; without knowing the details of that war, I couldn't say
  1272. how much of Finland also suffered this calendrical quirk.
  1273.  
  1274. Hans Mulder (hansm@cs.kun.nl) asks:
  1275.  
  1276. > >   (2) Thursday 4 October 1582 (Julian calendar) would be followed
  1277. > >       by Friday 15 October 1582 (Gregorian calendar). The gap of
  1278. > >       10 days corrected the accumulated error in the Julian
  1279. > >       calendar.
  1280. > Errhm, I would think that the accumulated error was 12 day: the years
  1281. > 100, 200, 300, 500, 600, 700, 900, 1000, 1100, 1300, 1400 and 1500 had
  1282. > been leap years, and under the new rules they shouldn't have been.
  1283. > Does anybody know why Gregory XIII skipped only 10 days?
  1284.  
  1285. Dating from the birth of Christ wasn't adopted in his own time -- if it
  1286. had been, presumably the correct year of his birth would have been used!
  1287. The idea was apparently to restore the calendar alignment that existed
  1288. around the time when this dating *was* adopted.  I don't know why the skip
  1289. was 10 days rather than 9 to match the year of the Council of Nicaea (325),
  1290. which established a number of Christian practices -- I assume that "AD"
  1291. dating was one of them.  The British law that I mentioned specifically
  1292. refers to the era of that council (which it spells Nice).
  1293. -- 
  1294. Mark Brader        "...the government is simply a bunch of people
  1295. SoftQuad Inc.         we've hired to protect ourselves from thieves and
  1296. Toronto             murderers and rapists and other governments..."
  1297. utzoo!sq!msb, msb@sq.com                -- Bill Stewart
  1298.  
  1299. This article is in the public domain.
  1300.  
  1301.  
  1302. Article 58353 (1190 more) in comp.lang.c:
  1303. From: dik@cwi.nl (Dik T. Winter)
  1304.  
  1305. Subject: Re: ******* DATES *********
  1306. Date: 24 Oct 92 01:53:34 GMT
  1307.  
  1308. In article <1992Oct23.133112.26368@black.ox.ac.uk> bob@black.ox.ac.uk (Bob Dougl
  1309. as) writes:
  1310.  > In article <BwJGJw.Fn3@sci.kun.nl> hansm@cs.kun.nl (Hans Mulder) writes:
  1311.  > >Errhm, I would think that the accumulated error was 12 day: the years
  1312.  > >100, 200, 300, 500, 600, 700, 900, 1000, 1100, 1300, 1400 and 1500 had
  1313.  > >been leap years, and under the new rules they shouldn't have been.
  1314.  > >
  1315.  > >Does anybody know why Gregory XIII skipped only 10 days?
  1316.  > >
  1317.  > I (who posted the above article) noticed this too. The Gregorian
  1318.  > amendment to the Julian calendar is such that, if the Gregorian
  1319.  > calendar is extrapolated backwards, the two calendars are in
  1320.  > agreement in the third century (from 1 March 200 to 28 February 300)
  1321.  > instead of in the first century (from 1 January 1 AD) when the
  1322.  > Julian calendar was two days ahead of the Gregorian one (it is now
  1323.  > 13 days behind). Why this is so I do not know.
  1324.  > 
  1325. The reason is simple.  The calendar reform had two main purposes, of which
  1326. one is generally known: to bring dates more in line with seasons throughout
  1327. the years.  The second (and in that time main) purpose was a new calculation
  1328. for easter (and that is also the reason why protestants were reluctant and
  1329. greek orthodox people are refusing to adopt the new calendar).  The slight
  1330. shift was to bring the start of spring closer to the 21nd of March (which
  1331. was not the case with the start of the Julian calendar).  The greek
  1332. orthodox church adopted a slightly different calendar, but the first time
  1333. you will see a difference is on 29 Feb 2700 (I think, this is from memory),
  1334. which does occur in the Gregorian calendar but not in the Greek orthodox one.
  1335. -- 
  1336. dik t. winter, cwi, kruislaan 413, 1098 sj  amsterdam, nederland
  1337. home: bovenover 215, 1025 jn  amsterdam, nederland; e-mail: dik@cwi.nl
  1338. SHAR_EOF
  1339. cat << \SHAR_EOF > data
  1340. ; beginning of Julian dates
  1341.        0    -4713  1  1 Mon   0
  1342.        1    -4713  1  2 Tue   1
  1343.        2    -4713  1  3 Wed   2
  1344.        3    -4713  1  4 Thu   3
  1345. ;
  1346. ; Julian calendar repeats every 4 years, at 365*4+1 = 1461 day intervals
  1347.   260424    -4000  1  1 Thu   0
  1348. ;   1461        4
  1349.   261885    -3996  1  1 Tue   0
  1350. ;   1461        4
  1351.   263346    -3992  1  1 Sun   0
  1352. ;
  1353. ; Julian dates near 1 AD (there was no year 0)
  1354.  1721420       -1 12 28 Tue 362
  1355.  1721421       -1 12 29 Wed 363
  1356.  1721422       -1 12 30 Thu 364
  1357.  1721423       -1 12 31 Fri 365
  1358.  1721424        1  1  1 Sat   0
  1359.  1721425        1  1  2 Sun   1
  1360.  1721426        1  1  3 Mon   2
  1361. ;
  1362. ;    usual transition dates are:
  1363. ;
  1364. ;    2299161 = October 5/15, 1582,       as in Rome, or
  1365. ;    2361222 = September 3/14, 1752,     as in the United Kingdom 
  1366. ;                                        and the Colonies (default)
  1367. ;
  1368. ; Julian dates near the transition...
  1369. ;          
  1370.  2361220       1752  9  1  Tue  244 
  1371.  2361221       1752  9  2  Wed  245 
  1372.  2361222       1752  9 14  Thu  246 
  1373.  2361223       1752  9 15  Fri  247 
  1374. T2299161                                ; as in Rome
  1375.  2299159     1582 10  3 Wed 275
  1376.  2299160     1582 10  4 Thu 276
  1377.  2299161     1582 10 15 Fri 277
  1378.  2299162     1582 10 16 Sat 278
  1379. ;
  1380. ; Apart from the 4000 year correction, the Gregorian calendar repeats 
  1381. ; every 400 years, or at ((365*4+1)*25-1)*4+1 = 146097 day intervals
  1382.  2302526     1592  1  1 Wed   0
  1383. ; 146097      400
  1384.  2448623     1992  1  1 Wed   0
  1385. ; 146097      400
  1386.  2594720     2392  1  1 Wed   0
  1387. ; 146097      400
  1388.  2740817     2792  1  1 Wed   0
  1389. ;
  1390. ; Including the 4000 year correction, the Gregorian calendar repeats 
  1391. ; at (((365*4+1)*25-1)*4+1)*10-1 = 1460969 day intervals
  1392.  2302526     1592  1  1 Wed   0
  1393. ;1460969     4000
  1394.  3763495     5592  1  1 Tue   0
  1395. ;1460969     4000
  1396.  5224464     9592  1  1 Mon   0
  1397. ;1460969     4000
  1398.  6685433    13592  1  1 Sun   0
  1399. ;
  1400. ;    The USNO time service reports the Modified Julian Date (MJD),
  1401. ;    which is figured by subtracting a constant (2,400,000.5) from the
  1402. ;    Julian Date as of the preceding midnight.
  1403. ;
  1404. ;    For example, the MJD for 7 Jul 92 was 48806
  1405. ;                              offset    2400000.5
  1406. ;                     JD at midnight was 2448806.5
  1407. ;                         JD at noon was 2448807
  1408. ;
  1409.  2448807     1992  7  3 Fri 184
  1410. ;
  1411. ; checks on day-of-week calculation...
  1412. ; "black Tuesday" 
  1413.  2425914     1929 10 29 Tue 301
  1414. ; "a day that will live in infamy"
  1415.  2430336     1941 12  7 Sun 340
  1416. ; "black Monday" 
  1417.  2447088     1987 10 19 Mon 291
  1418. SHAR_EOF
  1419. cat << \SHAR_EOF > makefile
  1420. CFLAGS= -v
  1421. tjul.exe: tjul.obj julcal.obj
  1422.     $(CC) -v tjul.obj julcal.obj
  1423. julcal.obj: julcal.c
  1424. tjul.obj: tjul.c julcal.h
  1425.     
  1426. distrib: julcal10.zip julcal.sh
  1427. julcal10.zip: julcal.c julcal.h tjul.c dates.txt data makefile makefile.ux
  1428.     echo Julian date routines |pkzip -uoz julcal10 julcal.c julcal.h tjul.c dates.txt data makefile makefile.ux
  1429. julcal.sh: julcal.c julcal.h tjul.c dates.txt data makefile makefile.ux
  1430.     shar julcal.c julcal.h tjul.c dates.txt data makefile makefile.ux >julcal.sh
  1431.  
  1432. clean:
  1433.     erase *.obj
  1434.     erase tjul.exe
  1435. SHAR_EOF
  1436. cat << \SHAR_EOF > makefile.ux
  1437. #CC=gcc
  1438. tjul: tjul.o julcal.o
  1439.     $(CC) $(CFLAGS) -o tjul tjul.o julcal.o
  1440. julcal.o: julcal.c
  1441.     gcc -DMKTIME -c julcal.c
  1442. tjul.o: tjul.c julcal.h
  1443.     
  1444. distrib: julcal10.zip
  1445. julcal10.zip: julcal.c julcal.h tjul.c dates.txt data makefile makefile.ux
  1446.     zip -o julcal10 julcal.c julcal.h tjul.c dates.txt data makefile makefile.ux
  1447.  
  1448. clean:
  1449.     rm *.o tjul
  1450. SHAR_EOF
  1451. #    End of shell archive
  1452. exit 0
  1453.