设为首页收藏本站

爱吱声

 找回密码
 注册
搜索
查看: 8272|回复: 33
打印 上一主题 下一主题

[科普知识] 程序员的历法

[复制链接]
  • TA的每日心情
    开心
    10 小时前
  • 签到天数: 3040 天

    [LV.Master]无

    跳转到指定楼层
    楼主
    发表于 2015-2-1 18:10:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本帖最后由 heinsect 于 2015-2-1 18:13 编辑 7 T8 A8 b9 X7 O+ o
    8 P2 E- v, e, F# G+ J: R( Y
    程序员计算日期是用儒略日的。
    4 O% J) Q' B9 N$ l* I
    / F& Z7 m5 Y5 c5 U2 p儒略日中的儒略和儒略历中的儒略的关系嘛,只是因为儒略日的发明人的爷爷葱白凯撒,给儿子用了大帝的名字。刚好儒略历也用了大帝的名字。9 `) y6 |/ M5 w  G1 W* O% Z: k% a
    : {& Z$ U$ @- |8 w$ i% R- P: D
    单用日期的话,儒略日是从某天开始的一个日的整数。两个儒略日的差值就是相差的天数。这样想计算两个日期间的差值,计算星期几就很简单了。至于那个开始日期,儒略日的零点,用起来的时候谁也不关心,我就不讲了。
    4 m* d2 o' Q. K( c# W# L- K/ J( J- x: O1 P0 S- |3 t$ G* a
    从格里高利历日期算儒略日(JDN)的公式是这个样子的:. {( z! p+ y1 w% I- [1 P& G% H% Z
    ) N( t( o1 p1 K
    先要改一下年月:& k, M7 m) w2 j( r- C- H

    * X# E$ V8 r/ ^; P9 N  Z3 `
    ' ~/ Y! x3 P# `& ^3 Q" g上面这组公式的结果呢,差不多是这个意思:
    . ~$ i- X2 v+ U7 k' _三月 m = 0, y=y- r& l( j" E/ y* @) G% \
    ...2 g  h" p9 F: Q3 {) n5 `
    十二月 m=9, y=y
    . S' J7 y4 f# p) j: n1 Q+ Z一月 m = 10, y=y-1
    0 ?) O7 _' ~' o9 D二月 m = 11, y=y-1; t# R" {, Z: {( C, k2 U4 ?) [
    . l% w. i- R, P! V7 T% R
    那个4800,是个计算零点,大概在公元前4801年,是和前面所说的那个零点相关的。
    - C4 Q, b* D7 k5 q0 ^7 z然后计算儒略日的公式长是这个样子的:
    " `6 u0 e! S8 E! X- K2 N
    ( L5 _% T1 b" J, d( B. _( @1 W4 Z8 t  R9 i5 e# z/ E

    6 z; b+ g3 j/ W# Q" ^# l$ D这个公式中最巧的部分是 floor((153m+2)/5), 做出的效果嘛,看这个表:
    + G. o) c( Y6 GMar–Jul:31 30 31 30 31Aug–Dec:31 30 31 30 31Jan–Feb:31 28$ m2 U8 M  ^/ g4 r& u* n) Z
    最后面的那个系数,是相对于原点的修正值。原公式算出来的值一般太大,计算中用起来会超过32/64位字长。现在天文计算中一般会选择2000年1月1日为零点,之前有用1900年和1950年的。
      \* f7 x: O9 k. p, U) t* ]$ Q3 x- s4 F( m6 h" c
    从儒略日计算星期几,(JDN+1) mod 7 就好了。
    : _& u* g2 B' I$ i1 T  e* Q# i/ ?% L7 w+ _. K3 n
    这个公式是怎么来的呢? 1582年,教皇格里高利十三(XIII)发现,那一年的春分是3月11日,和儒略历里规定的日期3月21日差了十天。原因嘛,就是回归年的长度是365.2422,儒略历用的365.25。格十三用上了全部的指头,哦,应该是找了很多XX家之后,下令当年10月4日的后一天是10月15日,同时规定在原先四年一闰的基础上,100的整数倍年不是闰年,但400的整数倍年又是闰年。新的历法改名为格里高利历。! z/ F7 L2 t/ C2 a

    * _  x9 a7 t* a2 H) J" }' N为了计算转换儒略历和格里高利历,一个法国的教会学者Joseph Justus Scaliger给出了这个公式。“儒略日”中的儒略,是他老爸的名字。6 u8 w+ X( l7 l

    & s3 m2 ~- W" c& h# `( x哦,原来的文献中用的是儒略历日期,要算儒略日是这样的:6 M; f5 {& O* y2 B% W% F
    ! o+ Y  U3 Y* y! k: \( ]. a( G; _

    $ x$ N! K$ ~) M- N: u5 H' L
    $ d2 `9 m1 a: i0 o- B5 m  K$ k从儒略日转格里高利历,也有一组公式,这里有:& K  m4 L6 B0 F6 N6 \4 ^6 G0 {5 n
    5 V- Z  e+ [. N0 B
    其实这些偏差,在儒略历启用之前是有人知道的。但是,始皇三十五年的某一天,一个罗马士兵在西西里岛上,拔出刀来,朝一个老人身上刺下去。这一刺,西方的科技文明停滞了一千多年。来自群组: 软件人家

    评分

    参与人数 6爱元 +35 学识 +5 收起 理由
    东张西望 + 10 + 5
    懒猫猫 + 8 不明觉厉
    水风 + 3 谢谢分享
    东湖珞珈 + 4 谢谢分享
    马鹿 + 8

    查看全部评分

  • TA的每日心情

    2020-3-6 00:28
  • 签到天数: 564 天

    [LV.9]渡劫

    沙发
    发表于 2015-2-1 19:18:36 | 只看该作者
    不明觉厉,捞分走人

    点评

    也捞一分~  发表于 2015-2-3 12:24

    该用户从未签到

    板凳
    发表于 2015-2-1 20:21:47 | 只看该作者
    程序员为啥不直接用格历?
  • TA的每日心情
    开心
    2026-4-13 22:08
  • 签到天数: 2733 天

    [LV.Master]无

    地板
    发表于 2015-2-2 01:20:49 | 只看该作者
    蛮夷的国家成了黑社会渊薮,大科学家的故乡开始赖账

    点评

    哈哈哈哈~  发表于 2015-2-2 02:31
  • TA的每日心情
    奋斗
    10 小时前
  • 签到天数: 2928 天

    [LV.Master]无

    5#
    发表于 2015-2-2 03:00:26 | 只看该作者
    不明觉厉
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-3-8 05:45
  • 签到天数: 2441 天

    [LV.Master]无

    6#
    发表于 2015-2-2 07:17:10 | 只看该作者
    N多年前学习BASIC语言的时候,就是用这个公式做核心计算,然后再加上几重循环控制的排版,打印一个当年的日历出来。
  • TA的每日心情
    开心
    2022-4-16 03:01
  • 签到天数: 192 天

    [LV.7]分神

    7#
    发表于 2015-2-2 09:53:15 | 只看该作者
    假装我看懂了,然后评分
  • TA的每日心情
    奋斗
    2020-8-27 18:47
  • 签到天数: 638 天

    [LV.9]渡劫

    8#
    发表于 2015-2-2 11:27:07 | 只看该作者
    能换算干支就更好了。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    9#
    发表于 2015-2-2 13:09:09 | 只看该作者
    看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多只需要计算某年是否是闰年就足够了。
  • TA的每日心情
    慵懒
    7 天前
  • 签到天数: 2868 天

    [LV.Master]无

    10#
    发表于 2015-2-2 13:52:01 | 只看该作者
    老兵帅客 发表于 2015-2-2 13:09" l) {4 M' Z' l8 `# G9 c" m2 @
    看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多 ...
    / l$ y2 z' \8 \3 w) y6 V
    试试计算下一千年每年复活节是哪一天,我又得昏过去了。。。哈哈哈。。。
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    11#
    发表于 2015-2-3 01:49:06 | 只看该作者
    老兵帅客 发表于 2015-2-2 13:09# {! {( S  y! n' c# ^
    看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多 ...

    % t1 ^! c. p6 b这个在当年可以用的日期函数还很罕见的时候有用。后来系统本身就提供这些计算了,自然没必要记。
    / \( g/ ^4 f/ }& ^4 k5 P+ P$ C/ \1 y; B' s
    我最早见到也是学BASIC的时候。$ S3 e3 X: @/ \" Y
      h$ P. s; [  e$ r& I/ M. I( r
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    12#
    发表于 2015-2-3 01:53:29 | 只看该作者
    本帖最后由 橡树村 于 2015-2-3 01:55 编辑
    1 ]& C8 ]  X  ?8 Y0 n; A! R
    hotmen 发表于 2015-2-2 11:27# s8 s, R, D0 Z0 a$ |: [& a
    能换算干支就更好了。

    5 l, }- C0 o, k5 D: f
    ) w% H! i( m9 C计算干支里面的日期不难,时辰是从日期推算的,也不难。
    . w4 D: `  W( n月份是按照年来推算的,说起来简单,难点在于一年以及一个月的开始时间的计算。这个很难有通用公式。不过还是比农历要简单,干支记年实际上是阳历,每年开始于立春,然后每间隔一个节气就换一个月,与农历的月份并不相同。这样只要有了节气的准确时间数据库,干支的问题也就解决了。5 j8 c/ ?6 s0 J
    , D, o- x" B- {* r
    农历复杂在于,这个历法经常被改动,要准确把历史上的某一天与西历进行换算,需要把曾经使用过的历法都考虑进去,这个麻烦就大了去了。而且每个月的开始取决于月亮的朔望,这就更要把历史上月亮的运行轨道都考虑进去了。
    ' F' C% k7 v+ r2 ~
    , O) l$ I* s5 w- v# Y7 F
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    13#
    发表于 2015-2-3 02:13:12 | 只看该作者
    橡树村 发表于 2015-2-2 12:49+ e3 b  K; j" R8 E4 M' A
    这个在当年可以用的日期函数还很罕见的时候有用。后来系统本身就提供这些计算了,自然没必要记。$ {0 W/ E8 x+ @& C# m0 ]/ _6 q. b: C

    5 K9 b9 ^; L  F我最早 ...

    9 o5 L: t) n3 o. a( M  Z( D问题是DOS下面的BASIC已经提供日期函数了啊,程序员何必再用这个?
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    14#
    发表于 2015-2-3 02:21:35 | 只看该作者
    老兵帅客 发表于 2015-2-3 02:13
    ' ~! E9 K- b" @0 Q: Z8 h9 Y- l问题是DOS下面的BASIC已经提供日期函数了啊,程序员何必再用这个?

    % [' t. k3 \; A不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程,最多弄个日历啥的。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    15#
    发表于 2015-2-3 02:29:31 | 只看该作者
    橡树村 发表于 2015-2-2 13:21( g9 F* O+ ]1 d/ K  q& `
    不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程 ...
    " {7 i# F5 E9 [2 O5 M) x2 y, U
    我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找出当前日期,然后自己计算闰年。计算闰年的算法很简单的,远比楼主的简单。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    16#
    发表于 2015-2-3 02:29:44 | 只看该作者
    橡树村 发表于 2015-2-2 13:217 _( ]7 ^7 q* q8 \' N- R
    不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程 ...

    ' L2 }. Z& E! k+ N我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找出当前日期,然后自己计算闰年。计算闰年的算法很简单的,远比楼主的简单。
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    17#
    发表于 2015-2-3 02:42:02 | 只看该作者
    老兵帅客 发表于 2015-2-3 02:29
    % ]8 G* Z; ~1 j4 I' S我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找 ...
    % A1 s3 f6 x$ Y' L
    Turbo Pascal?" h* p! N4 O9 A6 f3 m9 G6 R

    ) \5 E0 W* l% @2 d. M8 f最早PC机带的BASIC函数很少的,和Pascal比不了。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    18#
    发表于 2015-2-3 02:44:42 | 只看该作者
    橡树村 发表于 2015-2-2 13:42
    , V7 S$ Z6 `! C4 T$ OTurbo Pascal?1 Z, |: T. B7 C  `

    / {+ ^3 m4 I, n; H; M0 E: u最早PC机带的BASIC函数很少的,和Pascal比不了。
    4 x3 x: L* A  D* k* P% E, F) E
    不,是标准PASCAL,用的是微软的编译器。我上学的时候还没出turbo pascal呢,后来这东西出来了,拿来一试,发现丫不兼容标准PASCAL嘿,于是再也没碰它。
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    19#
    发表于 2015-2-3 02:52:31 | 只看该作者
    老兵帅客 发表于 2015-2-3 02:44# q; H9 ~" H# P: ~4 V
    不,是标准PASCAL,用的是微软的编译器。我上学的时候还没出turbo pascal呢,后来这东西出来了,拿来一试 ...

    & H6 q$ c( @5 |" r" I  E& S3 hTurbo pascal 是83年的,那时候我还不知道计算机长啥样呢。
    6 h  S/ [+ c" h) l# [3 A- H
    + f  z( r1 I; z, z我最早是在Comx35机器上接触的BASIC,84年。

    评分

    参与人数 1爱元 +4 收起 理由
    七月群山 + 4 伙呆了

    查看全部评分

  • TA的每日心情
    奋斗
    2024-3-8 05:45
  • 签到天数: 2441 天

    [LV.Master]无

    20#
    发表于 2015-2-3 04:01:00 | 只看该作者
    橡树村 发表于 2015-2-3 02:529 O5 R( n6 `& z; F- H
    Turbo pascal 是83年的,那时候我还不知道计算机长啥样呢。
    ( x) t. i+ E% e- u! \# t$ ^% U3 s0 A$ G2 u. l- o% Y
    我最早是在Comx35机器上接触的BASIC,84年。 ...

    1 W, J3 k; T' K村子老资格啊

    手机版|小黑屋|Archiver|网站错误报告|爱吱声   

    GMT+8, 2026-4-27 10:44 , Processed in 0.079354 second(s), 18 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表