1 /* This file is taken from http://www.genealogy.org/~scottlee/
2 Only this initial comment has been added. The next comment
3 gives the original copyright notice.
7 /* $selId: gregor.c,v 2.0 1995/10/24 01:13:06 lees Exp $
8 * Copyright 1993-1995, Scott E. Lee, all rights reserved.
9 * Permission granted to use, copy, modify, distribute and sell so long as
10 * the above copyright and this permission statement are retained in all
11 * copies. THERE IS NO WARRANTY - USE AT YOUR OWN RISK.
14 /**************************************************************************
16 * These are the externally visible components of this file:
25 * Convert a SDN to a Gregorian calendar date. If the input SDN is less
26 * than 1, the three output values will all be set to zero, otherwise
27 * *pYear will be >= -4714 and != 0; *pMonth will be in the range 1 to 12
28 * inclusive; *pDay will be in the range 1 to 31 inclusive.
36 * Convert a Gregorian calendar date to a SDN. Zero is returned when the
37 * input date is detected as invalid or out of the supported range. The
38 * return value will be > 0 for all valid, supported dates, but there are
39 * some invalid dates that will return a positive value. To verify that a
40 * date is valid, convert it to SDN and then back and compare with the
43 * char *MonthNameShort[13];
45 * Convert a Gregorian month number (1 to 12) to the abbreviated (three
46 * character) name of the Gregorian month (null terminated). An index of
47 * zero will return a zero length string.
49 * char *MonthNameLong[13];
51 * Convert a Gregorian month number (1 to 12) to the name of the Gregorian
52 * month (null terminated). An index of zero will return a zero length
57 * 4714 B.C. to at least 10000 A.D.
59 * Although this software can handle dates all the way back to 4714
60 * B.C., such use may not be meaningful. The Gregorian calendar was
61 * not instituted until October 15, 1582 (or October 5, 1582 in the
62 * Julian calendar). Some countries did not accept it until much
63 * later. For example, Britain converted in 1752, The USSR in 1918 and
64 * Greece in 1923. Most European countries used the Julian calendar
65 * prior to the Gregorian.
69 * The Gregorian calendar is a modified version of the Julian calendar.
70 * The only difference being the specification of leap years. The
71 * Julian calendar specifies that every year that is a multiple of 4
72 * will be a leap year. This leads to a year that is 365.25 days long,
73 * but the current accepted value for the tropical year is 365.242199
76 * To correct this error in the length of the year and to bring the
77 * vernal equinox back to March 21, Pope Gregory XIII issued a papal
78 * bull declaring that Thursday October 4, 1582 would be followed by
79 * Friday October 15, 1582 and that centennial years would only be a
80 * leap year if they were a multiple of 400. This shortened the year
81 * by 3 days per 400 years, giving a year of 365.2425 days.
83 * Another recently proposed change in the leap year rule is to make
84 * years that are multiples of 4000 not a leap year, but this has never
85 * been officially accepted and this rule is not implemented in these
90 * The calculations are based on three different cycles: a 400 year
91 * cycle of leap years, a 4 year cycle of leap years and a 5 month
92 * cycle of month lengths.
94 * The 5 month cycle is used to account for the varying lengths of
95 * months. You will notice that the lengths alternate between 30
96 * and 31 days, except for three anomalies: both July and August
97 * have 31 days, both December and January have 31, and February
98 * is less than 30. Starting with March, the lengths are in a
99 * cycle of 5 months (31, 30, 31, 30, 31):
103 * May 31 days > First cycle
109 * Oct 31 days > Second cycle
115 * > Third cycle (incomplete)
117 * For this reason the calculations (internally) assume that the
118 * year starts with March 1.
122 * This algorithm has been tested from the year 4714 B.C. to 10000
123 * A.D. The source code of the verification program is included in
128 * Conversions Between Calendar Date and Julian Day Number by Robert J.
129 * Tantzen, Communications of the Association for Computing Machinery
130 * August 1963. (Also published in Collected Algorithms from CACM,
131 * algorithm number 199).
133 **************************************************************************/
137 #define SDN_OFFSET 32045
138 #define DAYS_PER_5_MONTHS 153
139 #define DAYS_PER_4_YEARS 1461
140 #define DAYS_PER_400_YEARS 146097
163 temp = (sdn + SDN_OFFSET) * 4 - 1;
165 /* Calculate the century (year/100). */
166 century = temp / DAYS_PER_400_YEARS;
168 /* Calculate the year and day of year (1 <= dayOfYear <= 366). */
169 temp = ((temp % DAYS_PER_400_YEARS) / 4) * 4 + 3;
170 year = (century * 100) + (temp / DAYS_PER_4_YEARS);
171 dayOfYear = (temp % DAYS_PER_4_YEARS) / 4 + 1;
173 /* Calculate the month and day of month. */
174 temp = dayOfYear * 5 - 3;
175 month = temp / DAYS_PER_5_MONTHS;
176 day = (temp % DAYS_PER_5_MONTHS) / 5 + 1;
178 /* Convert to the normal beginning of the year. */
186 /* Adjust to the B.C./A.D. type numbering. */
188 if (year <= 0) year--;
204 /* check for invalid dates */
205 if (inputYear == 0 || inputYear < -4714 ||
206 inputMonth <= 0 || inputMonth > 12 ||
207 inputDay <= 0 || inputDay > 31)
212 /* check for dates before SDN 1 (Nov 25, 4714 B.C.) */
213 if (inputYear == -4714) {
214 if (inputMonth < 11) {
217 if (inputMonth == 11 && inputDay < 25) {
222 /* Make year always a positive number. */
224 year = inputYear + 4801;
226 year = inputYear + 4800;
229 /* Adjust the start of the year. */
230 if (inputMonth > 2) {
231 month = inputMonth - 3;
233 month = inputMonth + 9;
237 return( ((year / 100) * DAYS_PER_400_YEARS) / 4
238 + ((year % 100) * DAYS_PER_4_YEARS) / 4
239 + (month * DAYS_PER_5_MONTHS + 2) / 5
244 char *MonthNameShort[13] = {
260 char *MonthNameLong[13] = {