X-Git-Url: https://git.dlugolecki.net.pl/?a=blobdiff_plain;f=gedcom%2Fcalendar%2Fjulian.c;fp=gedcom%2Fcalendar%2Fjulian.c;h=e2c955a79a7975aebfd2c3bd4c111b428b51d547;hb=410d63fd737654b7e6b2b14f6a4ad8c810c3ab13;hp=0000000000000000000000000000000000000000;hpb=d3934f67da413f5bc18a927cc0b13503831cc1f3;p=gedcom-parse.git diff --git a/gedcom/calendar/julian.c b/gedcom/calendar/julian.c new file mode 100644 index 0000000..e2c955a --- /dev/null +++ b/gedcom/calendar/julian.c @@ -0,0 +1,251 @@ +/* This file is taken from http://www.genealogy.org/~scottlee/ + Only this initial comment has been added. The next comment + gives the original copyright notice. +*/ + + +/* $selId: julian.c,v 2.0 1995/10/24 01:13:06 lees Exp $ + * Copyright 1993-1995, Scott E. Lee, all rights reserved. + * Permission granted to use, copy, modify, distribute and sell so long as + * the above copyright and this permission statement are retained in all + * copies. THERE IS NO WARRANTY - USE AT YOUR OWN RISK. + */ + +/************************************************************************** + * + * These are the externally visible components of this file: + * + * void + * SdnToJulian( + * long int sdn, + * int *pYear, + * int *pMonth, + * int *pDay); + * + * Convert a SDN to a Julian calendar date. If the input SDN is less than + * 1, the three output values will all be set to zero, otherwise *pYear + * will be >= -4713 and != 0; *pMonth will be in the range 1 to 12 + * inclusive; *pDay will be in the range 1 to 31 inclusive. + * + * long int + * JulianToSdn( + * int inputYear, + * int inputMonth, + * int inputDay); + * + * Convert a Julian calendar date to a SDN. Zero is returned when the + * input date is detected as invalid or out of the supported range. The + * return value will be > 0 for all valid, supported dates, but there are + * some invalid dates that will return a positive value. To verify that a + * date is valid, convert it to SDN and then back and compare with the + * original. + * + * VALID RANGE + * + * 4713 B.C. to at least 10000 A.D. + * + * Although this software can handle dates all the way back to 4713 + * B.C., such use may not be meaningful. The calendar was created in + * 46 B.C., but the details did not stabilize until at least 8 A.D., + * and perhaps as late at the 4th century. Also, the beginning of a + * year varied from one culture to another - not all accepted January + * as the first month. + * + * CALENDAR OVERVIEW + * + * Julias Ceasar created the calendar in 46 B.C. as a modified form of + * the old Roman republican calendar which was based on lunar cycles. + * The new Julian calendar set fixed lengths for the months, abandoning + * the lunar cycle. It also specified that there would be exactly 12 + * months per year and 365.25 days per year with every 4th year being a + * leap year. + * + * Note that the current accepted value for the tropical year is + * 365.242199 days, not 365.25. This lead to an 11 day shift in the + * calendar with respect to the seasons by the 16th century when the + * Gregorian calendar was created to replace the Julian calendar. + * + * The difference between the Julian and today's Gregorian calendar is + * that the Gregorian does not make centennial years leap years unless + * they are a multiple of 400, which leads to a year of 365.2425 days. + * In other words, in the Gregorian calendar, 1700, 1800 and 1900 are + * not leap years, but 2000 is. All centennial years are leap years in + * the Julian calendar. + * + * The details are unknown, but the lengths of the months were adjusted + * until they finally stablized in 8 A.D. with their current lengths: + * + * January 31 + * February 28/29 + * March 31 + * April 30 + * May 31 + * June 30 + * Quintilis/July 31 + * Sextilis/August 31 + * September 30 + * October 31 + * November 30 + * December 31 + * + * In the early days of the calendar, the days of the month were not + * numbered as we do today. The numbers ran backwards (decreasing) and + * were counted from the Ides (15th of the month - which in the old + * Roman republican lunar calendar would have been the full moon) or + * from the Nonae (9th day before the Ides) or from the beginning of + * the next month. + * + * In the early years, the beginning of the year varied, sometimes + * based on the ascension of rulers. It was not always the first of + * January. + * + * Also, today's epoch, 1 A.D. or the birth of Jesus Christ, did not + * come into use until several centuries later when Christianity became + * a dominant religion. + * + * ALGORITHMS + * + * The calculations are based on two different cycles: a 4 year cycle + * of leap years and a 5 month cycle of month lengths. + * + * The 5 month cycle is used to account for the varying lengths of + * months. You will notice that the lengths alternate between 30 and + * 31 days, except for three anomalies: both July and August have 31 + * days, both December and January have 31, and February is less than + * 30. Starting with March, the lengths are in a cycle of 5 months + * (31, 30, 31, 30, 31): + * + * Mar 31 days \ + * Apr 30 days | + * May 31 days > First cycle + * Jun 30 days | + * Jul 31 days / + * + * Aug 31 days \ + * Sep 30 days | + * Oct 31 days > Second cycle + * Nov 30 days | + * Dec 31 days / + * + * Jan 31 days \ + * Feb 28/9 days | + * > Third cycle (incomplete) + * + * For this reason the calculations (internally) assume that the year + * starts with March 1. + * + * TESTING + * + * This algorithm has been tested from the year 4713 B.C. to 10000 A.D. + * The source code of the verification program is included in this + * package. + * + * REFERENCES + * + * Conversions Between Calendar Date and Julian Day Number by Robert J. + * Tantzen, Communications of the Association for Computing Machinery + * August 1963. (Also published in Collected Algorithms from CACM, + * algorithm number 199). [Note: the published algorithm is for the + * Gregorian calendar, but was adjusted to use the Julian calendar's + * simpler leap year rule.] + * + **************************************************************************/ + +#include "sdncal.h" + +#define SDN_OFFSET 32083 +#define DAYS_PER_5_MONTHS 153 +#define DAYS_PER_4_YEARS 1461 + +void +SdnToJulian( + long int sdn, + int *pYear, + int *pMonth, + int *pDay) +{ + int year; + int month; + int day; + long int temp; + int dayOfYear; + + if (sdn <= 0) { + *pYear = 0; + *pMonth = 0; + *pDay = 0; + return; + } + + temp = (sdn + SDN_OFFSET) * 4 - 1; + + /* Calculate the year and day of year (1 <= dayOfYear <= 366). */ + year = temp / DAYS_PER_4_YEARS; + dayOfYear = (temp % DAYS_PER_4_YEARS) / 4 + 1; + + /* Calculate the month and day of month. */ + temp = dayOfYear * 5 - 3; + month = temp / DAYS_PER_5_MONTHS; + day = (temp % DAYS_PER_5_MONTHS) / 5 + 1; + + /* Convert to the normal beginning of the year. */ + if (month < 10) { + month += 3; + } else { + year += 1; + month -= 9; + } + + /* Adjust to the B.C./A.D. type numbering. */ + year -= 4800; + if (year <= 0) year--; + + *pYear = year; + *pMonth = month; + *pDay = day; +} + +long int +JulianToSdn( + int inputYear, + int inputMonth, + int inputDay) +{ + int year; + int month; + + /* check for invalid dates */ + if (inputYear == 0 || inputYear < -4713 || + inputMonth <= 0 || inputMonth > 12 || + inputDay <= 0 || inputDay > 31) + { + return(0); + } + + /* check for dates before SDN 1 (Jan 2, 4713 B.C.) */ + if (inputYear == -4713) { + if (inputMonth == 1 && inputDay == 1) { + return(0); + } + } + + /* Make year always a positive number. */ + if (inputYear < 0) { + year = inputYear + 4801; + } else { + year = inputYear + 4800; + } + + /* Adjust the start of the year. */ + if (inputMonth > 2) { + month = inputMonth - 3; + } else { + month = inputMonth + 9; + year--; + } + + return( (year * DAYS_PER_4_YEARS) / 4 + + (month * DAYS_PER_5_MONTHS + 2) / 5 + + inputDay + - SDN_OFFSET ); +}