heinsect 发表于 2015-2-1 18:10:26

程序员的历法

本帖最后由 heinsect 于 2015-2-1 18:13 编辑

程序员计算日期是用儒略日的。

儒略日中的儒略和儒略历中的儒略的关系嘛,只是因为儒略日的发明人的爷爷葱白凯撒,给儿子用了大帝的名字。刚好儒略历也用了大帝的名字。

单用日期的话,儒略日是从某天开始的一个日的整数。两个儒略日的差值就是相差的天数。这样想计算两个日期间的差值,计算星期几就很简单了。至于那个开始日期,儒略日的零点,用起来的时候谁也不关心,我就不讲了。

从格里高利历日期算儒略日(JDN)的公式是这个样子的:

先要改一下年月:
http://upload.wikimedia.org/math/5/a/1/5a119ca71c25ba56dc43d66741b291c6.png

上面这组公式的结果呢,差不多是这个意思:
三月 m = 0, y=y
...
十二月 m=9, y=y
一月 m = 10, y=y-1
二月 m = 11, y=y-1

那个4800,是个计算零点,大概在公元前4801年,是和前面所说的那个零点相关的。
然后计算儒略日的公式长是这个样子的:

http://upload.wikimedia.org/math/a/9/8/a984ffed25e734840873c700eecf5877.png

这个公式中最巧的部分是 floor((153m+2)/5), 做出的效果嘛,看这个表:
Mar–Jul:31 30 31 30 31Aug–Dec:31 30 31 30 31Jan–Feb:31 28
最后面的那个系数,是相对于原点的修正值。原公式算出来的值一般太大,计算中用起来会超过32/64位字长。现在天文计算中一般会选择2000年1月1日为零点,之前有用1900年和1950年的。

从儒略日计算星期几,(JDN+1) mod 7 就好了。

这个公式是怎么来的呢? 1582年,教皇格里高利十三(XIII)发现,那一年的春分是3月11日,和儒略历里规定的日期3月21日差了十天。原因嘛,就是回归年的长度是365.2422,儒略历用的365.25。格十三用上了全部的指头,哦,应该是找了很多XX家之后,下令当年10月4日的后一天是10月15日,同时规定在原先四年一闰的基础上,100的整数倍年不是闰年,但400的整数倍年又是闰年。新的历法改名为格里高利历。

为了计算转换儒略历和格里高利历,一个法国的教会学者Joseph Justus Scaliger给出了这个公式。“儒略日”中的儒略,是他老爸的名字。

哦,原来的文献中用的是儒略历日期,要算儒略日是这样的:

http://upload.wikimedia.org/math/f/0/0/f0093db2275d3718add6fcaf459062c6.png

从儒略日转格里高利历,也有一组公式,这里有:

其实这些偏差,在儒略历启用之前是有人知道的。但是,始皇三十五年的某一天,一个罗马士兵在西西里岛上,拔出刀来,朝一个老人身上刺下去。这一刺,西方的科技文明停滞了一千多年。软件人家

穿着裤衩裸奔 发表于 2015-2-1 19:18:36

不明觉厉,捞分走人

孟词宗 发表于 2015-2-1 20:21:47

程序员为啥不直接用格历?

龙血树 发表于 2015-2-2 01:20:49

蛮夷的国家成了黑社会渊薮,大科学家的故乡开始赖账

方恨少 发表于 2015-2-2 03:00:26

不明觉厉

东湖珞珈 发表于 2015-2-2 07:17:10

N多年前学习BASIC语言的时候,就是用这个公式做核心计算,然后再加上几重循环控制的排版,打印一个当年的日历出来。

水风 发表于 2015-2-2 09:53:15

假装我看懂了,然后评分{:214:}

hotmen 发表于 2015-2-2 11:27:07

能换算干支就更好了。

老兵帅客 发表于 2015-2-2 13:09:09

看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多只需要计算某年是否是闰年就足够了。

夏翁 发表于 2015-2-2 13:52:01

老兵帅客 发表于 2015-2-2 13:09
看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多 ...

试试计算下一千年每年复活节是哪一天,我又得昏过去了。。。哈哈哈。。。

橡树村 发表于 2015-2-3 01:49:06

老兵帅客 发表于 2015-2-2 13:09
看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多 ...

这个在当年可以用的日期函数还很罕见的时候有用。后来系统本身就提供这些计算了,自然没必要记。

我最早见到也是学BASIC的时候。

橡树村 发表于 2015-2-3 01:53:29

本帖最后由 橡树村 于 2015-2-3 01:55 编辑

hotmen 发表于 2015-2-2 11:27
能换算干支就更好了。

计算干支里面的日期不难,时辰是从日期推算的,也不难。
月份是按照年来推算的,说起来简单,难点在于一年以及一个月的开始时间的计算。这个很难有通用公式。不过还是比农历要简单,干支记年实际上是阳历,每年开始于立春,然后每间隔一个节气就换一个月,与农历的月份并不相同。这样只要有了节气的准确时间数据库,干支的问题也就解决了。

农历复杂在于,这个历法经常被改动,要准确把历史上的某一天与西历进行换算,需要把曾经使用过的历法都考虑进去,这个麻烦就大了去了。而且每个月的开始取决于月亮的朔望,这就更要把历史上月亮的运行轨道都考虑进去了。

老兵帅客 发表于 2015-2-3 02:13:12

橡树村 发表于 2015-2-2 12:49
这个在当年可以用的日期函数还很罕见的时候有用。后来系统本身就提供这些计算了,自然没必要记。

我最早 ...

问题是DOS下面的BASIC已经提供日期函数了啊,程序员何必再用这个?

橡树村 发表于 2015-2-3 02:21:35

老兵帅客 发表于 2015-2-3 02:13
问题是DOS下面的BASIC已经提供日期函数了啊,程序员何必再用这个?

不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程,最多弄个日历啥的。

老兵帅客 发表于 2015-2-3 02:29:31

橡树村 发表于 2015-2-2 13:21
不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程 ...

我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找出当前日期,然后自己计算闰年。计算闰年的算法很简单的,远比楼主的简单。

老兵帅客 发表于 2015-2-3 02:29:44

橡树村 发表于 2015-2-2 13:21
不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程 ...

我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找出当前日期,然后自己计算闰年。计算闰年的算法很简单的,远比楼主的简单。

橡树村 发表于 2015-2-3 02:42:02

老兵帅客 发表于 2015-2-3 02:29
我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找 ...

Turbo Pascal?

最早PC机带的BASIC函数很少的,和Pascal比不了。

老兵帅客 发表于 2015-2-3 02:44:42

橡树村 发表于 2015-2-2 13:42
Turbo Pascal?

最早PC机带的BASIC函数很少的,和Pascal比不了。

不,是标准PASCAL,用的是微软的编译器。我上学的时候还没出turbo pascal呢,后来这东西出来了,拿来一试,发现丫不兼容标准PASCAL嘿,于是再也没碰它。

橡树村 发表于 2015-2-3 02:52:31

老兵帅客 发表于 2015-2-3 02:44
不,是标准PASCAL,用的是微软的编译器。我上学的时候还没出turbo pascal呢,后来这东西出来了,拿来一试 ...

Turbo pascal 是83年的,那时候我还不知道计算机长啥样呢。

我最早是在Comx35机器上接触的BASIC,84年。

东湖珞珈 发表于 2015-2-3 04:01:00

橡树村 发表于 2015-2-3 02:52
Turbo pascal 是83年的,那时候我还不知道计算机长啥样呢。

我最早是在Comx35机器上接触的BASIC,84年。 ...

村子老资格啊
页: [1] 2
查看完整版本: 程序员的历法