日期:2014-05-20  浏览次数:20893 次

历史上“丢失”的十天——编程中的日期问题
公历和农历由来 历史上"丢失"的10天:1582年月10月5日至1582年月10月14日

以回归年周期为主要依据所编制的“太阳历” 

太阳历又称“阳历”。它不考虑月相的变化如何,只考虑地球绕日公转一周即一个回归年的时间长短。我们知道,地球总是斜着身子绕日不停地作圆周运动,公转一周的时间是365.2422日(即365天5时48分46秒)。如果人为地设置十二个月,小月为三十天,大月为三十一天,仍然由于一回归年后有一个小数点尾巴带来的问题。后来人们又想出了设置闰年的办法来解决这个问题,譬如平年365天,闰年366天,以便保证阳历年的长度与实际回归年的长度基本吻合。 

与西汉王朝同时代的古罗马帝国也是文明古国之一,曾经使用的是以朔望月为依据的阴历,后来为了协调与回归年的关系,采用了各种设置闰月的办法,但始终是一个混乱无序的“阴阳历”。公元前四十六年,儒略.恺撒掌握军政大权后,聘请了天文学家索西琴改革历法,其要点是: 
1、全年十二个月,单月为大月三十一天,双月为小月三十天,平年的二月为二十九天,全年共计三百六十五天, 
2、冬至后十月为一年的开始,即为每年的岁首。 
3、从改历的下一年起,每三年是一闰年,闰年共计三百六十六天,所多的一天放在二月尾,为三十天。 

这就是现行流行的阳历的前身,一般称“儒略历”,其中七月因儒略.恺撒的出生而命名为“儒略月”。然而负责执行的僧侣们误把“每隔三年置一闰年”理解为“每三年置一闰年”,并一直错误执行了三十多年,到公元前九年屋大维(即奥古斯都)统治时,人们发现三十多年中已多设置了闰年五次,于是屋大维下令在以后的一段年份里少设三次闰年,并恢复原来每四年设置一闰的规定。屋大维是把自己的出生的八月命名为奥古斯都月,于是把原来属于小月的八月改为大月,多出的一天从二月中扣出。同时,为了避免一连三个大月,又把九月和十一月改为小月,十月和十二月改为大月。这一不合理的规定一直延续到现在。 

儒略历规定每年平均长度是365.25天,比实际回归年长出0.0078天,即每年长出12分14秒。这点差值在短期内难以发现,但只要过128年,历法规定的年就要多出回归年一天,公元325年,至高无尚的的欧洲基督教教会召开宗教大会,一致确定儒略历是最准确的历法并全面推行。并根据天文观测和宗教活动的需要,规定春分日必须是三月二十一日,而纪念耶稣死后复活的复活节定在春分满月后的第一个星期日,到公元1582年,随着哥白尼太阳中心说的确认和天文观测的技术的进步,发现实际春分时刻已提前到三月十一日,比原定的三月二十一日提前十天,当时的罗马教皇格列高列十三世便召集天文学者和僧侣们商讨改历问题,最后决定采用天文学家利里奥的改革方案。 

1、为使春分时刻再回到三月二十一日,把1582年月10月4日以后的一天改为10月15日,从中删去10天。 
2、采用400年97闰法,即凡公元年号能被4整除为闰年,但公元年号为整百年时,须能被400整除者方为闰年,(如1600年、2000年)。其它为平年(如1700年、1900年)。 

这就是目前世界上通用的阳历,又称“格列历”。至于岁首和纪元的设置,也是人为而定。现在的岁首是儒略.恺撒颁布历法时规定的,即定在冬至后十天为一月一日,因此有“冬至十天阳历年”的说法。古代欧洲和我国过去一样常采用“王位纪年法”,即将某个统治者登基作为纪年的开始,在西欧的罗马帝国则以罗马统治者狄奥.支列颠称帝时作为纪年的开始。后来有个叫狄奥尼亚的基督僧侣在预先推算狄奥支列颠纪元248年的“复活节”日期时,提出所谓耶稣诞生于狄奥.支列颠纪元前284年的说法,并主张以耶稣诞生的一年为纪元。它的主张竟然得到教会的大力支持,这样,狄奥支列颠248年就成为耶稣诞生纪年的532年。因此,现行的公历纪年,实际上从公元532年才在一些地区开始实行,到现在逐步成为全世界通用的正式纪年.


独具特色的我国农历 

与现行阳历并用的农历,一直是我国的传统历法,也是我国古代以来农民安排农事活动的重要依据。因此,称之为“农历”。其大致的做法是: 
1、朔望月周期是29.5306天,因此农历规定大月三十天,小月二十九天,但大小月并不因定顺序,而是由两次合朔之间的天数来决定。前提为凡是有合朔时刻的一天,必定为初 
2、若一年为十二个月,共计354天多,比实际回归年少11天多,长此下去月序与节令气候不吻合,因此采取设置闰月的办法来调整。大概在春秋时代采用“十九年七闰的办法,即每十九年,插入七个月,一般还把不会“中合”的月份定为闰年(二十四节中,单数则叫“节气”,双数则叫“中气”。) 

二十四节气是我国劳动人民的一个创造。它能准确地反映太阳在黄道上的位置,生动地体现了地面上寒暑四季变化的循环规律,同时也具有鲜明的节气特点和浓郁的乡土气息,主要是黄河中下游地区。共顺序依次是:立春,雨水,惊蛰,春分,清明,谷雨,立夏,小满,芒种,夏至,大暑、小暑、立秋、处暑、白露、秋分、寒露、霜降、立冬、小雪、大雪、冬至、小寒、大寒。从它的含义上看,有反映天象的,如立春、春分、立夏、夏至、立秋、秋分、立冬、冬至,其中夏至和冬至是太阳直射点分别在北回归线和南回归线的时刻,而春分与秋分时太阳直射点均在赤道上。也有表示气候的,如雨水、清明、谷雨、小暑、大暑、处暑、白露、寒露、霜降、小雪、大雪、小寒、大寒。还有表示物候的,如惊蛰、小满、满种等。下面根据二十四节气编成的谚语能反映出节气与农事安排的关系。如“立春耕牛走”,“清明种瓜豆”,“谷雨播大田”,“小满粒长满”,“芒种忙收种”,“夏至秧苗全”,“处暑备也镰”,“小寒忙买办”,“白露谷登场”,“大寒要过年”,为了便于记记忆,二十四节气中每取一字,可能编成一首顺口溜。“春雨惊春清谷天,夏满芒夏暑相连,秋处露秋寒霜降,冬雪雪冬大小寒”。 

农历还有一套特有的纪年和纪日方法,就是所谓的“干支纪法”。干支即“天干”“地支”的总称,以甲、乙、丙、丁、戌、已、庚、辛、王、癸、申10个这字为“天干”,以子丑、寅、卯、辰、已、午、未、申、酉、戌、亥十二个字为“地支”,并让相应的天干与地支有序组合,便可得到60以不同的干支,60年一个循环,往复不断。到了近代人们习惯有用干支纪年来表明某些重要的历史事件,如1894年的甲午战争,1898年的辛亥革命。干支纪法比较繁琐,此不评述。

因为这方面的原因,有些编程语言对这段时间的处理会出错,比如C#就会出错,下面就是示例代码:
C# code

using System;

class GregorianTest
{
    static void Main()
    {
        //消失的十天为1582年月10月5日至1582年月10月14日
        DateTime dt1 = new DateTime(1582, 10, 4);
        Console.WriteLine(dt1.ToString("dddd yyyy-MM-dd"));
        //按照道理加一天之后应该为1582-10-05了
        Console.WriteLine(dt1.AddDays(1).ToString("dddd yyyy-MM-dd"));
        //按照道路这一天应该不是1582-10-06了
        Console.WriteLine(dt1.AddDays(2).ToString("dddd yyyy-MM-dd"));
        
        DateTime dt2=new DateTime(1582,10,14);
        Console.WriteLine(dt2.ToString("dddd yyyy-MM-dd"));
        //按理说不存在1582-10-13
        Console.WriteLine(dt2.AddDays(-1).ToString("dddd yyyy-MM-dd"));
        ////按理说不存在1582-10-12
        Console.WriteLine(dt2.AddDays(-2).ToString("dddd yyyy-MM-dd"));
    }
}



------解决方案--------------------
前排.