php5
5.3.10

00001 /* $selId: julian.c,v 2.0 1995/10/24 01:13:06 lees Exp $ 00002 * Copyright 19931995, Scott E. Lee, all rights reserved. 00003 * Permission granted to use, copy, modify, distribute and sell so long as 00004 * the above copyright and this permission statement are retained in all 00005 * copies. THERE IS NO WARRANTY  USE AT YOUR OWN RISK. 00006 */ 00007 00008 /************************************************************************** 00009 * 00010 * These are the externally visible components of this file: 00011 * 00012 * void 00013 * SdnToJulian( 00014 * long int sdn, 00015 * int *pYear, 00016 * int *pMonth, 00017 * int *pDay); 00018 * 00019 * Convert a SDN to a Julian calendar date. If the input SDN is less than 00020 * 1, the three output values will all be set to zero, otherwise *pYear 00021 * will be >= 4713 and != 0; *pMonth will be in the range 1 to 12 00022 * inclusive; *pDay will be in the range 1 to 31 inclusive. 00023 * 00024 * long int 00025 * JulianToSdn( 00026 * int inputYear, 00027 * int inputMonth, 00028 * int inputDay); 00029 * 00030 * Convert a Julian calendar date to a SDN. Zero is returned when the 00031 * input date is detected as invalid or out of the supported range. The 00032 * return value will be > 0 for all valid, supported dates, but there are 00033 * some invalid dates that will return a positive value. To verify that a 00034 * date is valid, convert it to SDN and then back and compare with the 00035 * original. 00036 * 00037 * VALID RANGE 00038 * 00039 * 4713 B.C. to at least 10000 A.D. 00040 * 00041 * Although this software can handle dates all the way back to 4713 00042 * B.C., such use may not be meaningful. The calendar was created in 00043 * 46 B.C., but the details did not stabilize until at least 8 A.D., 00044 * and perhaps as late at the 4th century. Also, the beginning of a 00045 * year varied from one culture to another  not all accepted January 00046 * as the first month. 00047 * 00048 * CALENDAR OVERVIEW 00049 * 00050 * Julias Ceasar created the calendar in 46 B.C. as a modified form of 00051 * the old Roman republican calendar which was based on lunar cycles. 00052 * The new Julian calendar set fixed lengths for the months, abandoning 00053 * the lunar cycle. It also specified that there would be exactly 12 00054 * months per year and 365.25 days per year with every 4th year being a 00055 * leap year. 00056 * 00057 * Note that the current accepted value for the tropical year is 00058 * 365.242199 days, not 365.25. This lead to an 11 day shift in the 00059 * calendar with respect to the seasons by the 16th century when the 00060 * Gregorian calendar was created to replace the Julian calendar. 00061 * 00062 * The difference between the Julian and today's Gregorian calendar is 00063 * that the Gregorian does not make centennial years leap years unless 00064 * they are a multiple of 400, which leads to a year of 365.2425 days. 00065 * In other words, in the Gregorian calendar, 1700, 1800 and 1900 are 00066 * not leap years, but 2000 is. All centennial years are leap years in 00067 * the Julian calendar. 00068 * 00069 * The details are unknown, but the lengths of the months were adjusted 00070 * until they finally stablized in 8 A.D. with their current lengths: 00071 * 00072 * January 31 00073 * February 28/29 00074 * March 31 00075 * April 30 00076 * May 31 00077 * June 30 00078 * Quintilis/July 31 00079 * Sextilis/August 31 00080 * September 30 00081 * October 31 00082 * November 30 00083 * December 31 00084 * 00085 * In the early days of the calendar, the days of the month were not 00086 * numbered as we do today. The numbers ran backwards (decreasing) and 00087 * were counted from the Ides (15th of the month  which in the old 00088 * Roman republican lunar calendar would have been the full moon) or 00089 * from the Nonae (9th day before the Ides) or from the beginning of 00090 * the next month. 00091 * 00092 * In the early years, the beginning of the year varied, sometimes 00093 * based on the ascension of rulers. It was not always the first of 00094 * January. 00095 * 00096 * Also, today's epoch, 1 A.D. or the birth of Jesus Christ, did not 00097 * come into use until several centuries later when Christianity became 00098 * a dominant religion. 00099 * 00100 * ALGORITHMS 00101 * 00102 * The calculations are based on two different cycles: a 4 year cycle 00103 * of leap years and a 5 month cycle of month lengths. 00104 * 00105 * The 5 month cycle is used to account for the varying lengths of 00106 * months. You will notice that the lengths alternate between 30 and 00107 * 31 days, except for three anomalies: both July and August have 31 00108 * days, both December and January have 31, and February is less than 00109 * 30. Starting with March, the lengths are in a cycle of 5 months 00110 * (31, 30, 31, 30, 31): 00111 * 00112 * Mar 31 days \ 00113 * Apr 30 days  00114 * May 31 days > First cycle 00115 * Jun 30 days  00116 * Jul 31 days / 00117 * 00118 * Aug 31 days \ 00119 * Sep 30 days  00120 * Oct 31 days > Second cycle 00121 * Nov 30 days  00122 * Dec 31 days / 00123 * 00124 * Jan 31 days \ 00125 * Feb 28/9 days  00126 * > Third cycle (incomplete) 00127 * 00128 * For this reason the calculations (internally) assume that the year 00129 * starts with March 1. 00130 * 00131 * TESTING 00132 * 00133 * This algorithm has been tested from the year 4713 B.C. to 10000 A.D. 00134 * The source code of the verification program is included in this 00135 * package. 00136 * 00137 * REFERENCES 00138 * 00139 * Conversions Between Calendar Date and Julian Day Number by Robert J. 00140 * Tantzen, Communications of the Association for Computing Machinery 00141 * August 1963. (Also published in Collected Algorithms from CACM, 00142 * algorithm number 199). [Note: the published algorithm is for the 00143 * Gregorian calendar, but was adjusted to use the Julian calendar's 00144 * simpler leap year rule.] 00145 * 00146 **************************************************************************/ 00147 00148 #include "sdncal.h" 00149 #include <limits.h> 00150 00151 #define JULIAN_SDN_OFFSET 32083 00152 #define DAYS_PER_5_MONTHS 153 00153 #define DAYS_PER_4_YEARS 1461 00154 00155 void SdnToJulian( 00156 long int sdn, 00157 int *pYear, 00158 int *pMonth, 00159 int *pDay) 00160 { 00161 int year; 00162 int month; 00163 int day; 00164 long int temp; 00165 int dayOfYear; 00166 00167 if (sdn <= 0) { 00168 goto fail; 00169 } 00170 /* Check for overflow */ 00171 if (sdn > (LONG_MAX  JULIAN_SDN_OFFSET * 4 + 1) / 4  sdn < LONG_MIN / 4) { 00172 goto fail; 00173 } 00174 temp = sdn * 4 + (JULIAN_SDN_OFFSET * 4  1); 00175 00176 /* Calculate the year and day of year (1 <= dayOfYear <= 366). */ 00177 { 00178 long yearl = temp / DAYS_PER_4_YEARS; 00179 if (yearl > INT_MAX  yearl < INT_MIN) { 00180 goto fail; 00181 } 00182 year = (int) yearl; 00183 } 00184 dayOfYear = (temp % DAYS_PER_4_YEARS) / 4 + 1; 00185 00186 /* Calculate the month and day of month. */ 00187 temp = dayOfYear * 5  3; 00188 month = temp / DAYS_PER_5_MONTHS; 00189 day = (temp % DAYS_PER_5_MONTHS) / 5 + 1; 00190 00191 /* Convert to the normal beginning of the year. */ 00192 if (month < 10) { 00193 month += 3; 00194 } else { 00195 year += 1; 00196 month = 9; 00197 } 00198 00199 /* Adjust to the B.C./A.D. type numbering. */ 00200 year = 4800; 00201 if (year <= 0) 00202 year; 00203 00204 *pYear = year; 00205 *pMonth = month; 00206 *pDay = day; 00207 return; 00208 00209 fail: 00210 *pYear = 0; 00211 *pMonth = 0; 00212 *pDay = 0; 00213 } 00214 00215 long int JulianToSdn( 00216 int inputYear, 00217 int inputMonth, 00218 int inputDay) 00219 { 00220 int year; 00221 int month; 00222 00223 /* check for invalid dates */ 00224 if (inputYear == 0  inputYear < 4713  00225 inputMonth <= 0  inputMonth > 12  00226 inputDay <= 0  inputDay > 31) { 00227 return (0); 00228 } 00229 /* check for dates before SDN 1 (Jan 2, 4713 B.C.) */ 00230 if (inputYear == 4713) { 00231 if (inputMonth == 1 && inputDay == 1) { 00232 return (0); 00233 } 00234 } 00235 /* Make year always a positive number. */ 00236 if (inputYear < 0) { 00237 year = inputYear + 4801; 00238 } else { 00239 year = inputYear + 4800; 00240 } 00241 00242 /* Adjust the start of the year. */ 00243 if (inputMonth > 2) { 00244 month = inputMonth  3; 00245 } else { 00246 month = inputMonth + 9; 00247 year; 00248 } 00249 00250 return ((year * DAYS_PER_4_YEARS) / 4 00251 + (month * DAYS_PER_5_MONTHS + 2) / 5 00252 + inputDay 00253  JULIAN_SDN_OFFSET); 00254 } 00255 00256 /* 00257 * Local variables: 00258 * tabwidth: 4 00259 * cbasicoffset: 4 00260 * End: 00261 * vim600: sw=4 ts=4 fdm=marker 00262 * vim<600: sw=4 ts=4 00263 */