设为首页收藏本站

爱吱声

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

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

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

    [LV.Master]无

    跳转到指定楼层
    楼主
    发表于 2015-2-1 18:10:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本帖最后由 heinsect 于 2015-2-1 18:13 编辑 + Q6 @6 ~$ s2 e! X$ h7 f

    ; T# N3 u" z1 p8 D5 j+ O程序员计算日期是用儒略日的。
    9 ^% d3 k. d$ g+ ]4 @5 K' f. J% s4 A) q
    儒略日中的儒略和儒略历中的儒略的关系嘛,只是因为儒略日的发明人的爷爷葱白凯撒,给儿子用了大帝的名字。刚好儒略历也用了大帝的名字。
    ! e+ ~2 Y& Q1 `( L5 W! h% {* D/ h  c) I' A+ T3 W! a
    单用日期的话,儒略日是从某天开始的一个日的整数。两个儒略日的差值就是相差的天数。这样想计算两个日期间的差值,计算星期几就很简单了。至于那个开始日期,儒略日的零点,用起来的时候谁也不关心,我就不讲了。
    . R8 A. ^/ B# W, y6 u3 r" \, T$ A3 a, j, o: Q" P
    从格里高利历日期算儒略日(JDN)的公式是这个样子的:+ u0 @3 C+ O3 T0 P: N

    * J7 u. u" b; M& B* G; w先要改一下年月:
    ( v/ d4 X( K; j/ e8 T6 Z& |2 O# L- K) K0 Y

    # ]  k9 r; g# U) e: ]- |% n. z上面这组公式的结果呢,差不多是这个意思:
    - B/ H" ]% t- I$ U( O' U8 a& e三月 m = 0, y=y+ G* f0 w& [; _+ B" h2 v/ ?5 H$ @
    ...
    + _$ L- ^9 n* d, S; }十二月 m=9, y=y% e8 p. {6 P) ]! g$ a$ R
    一月 m = 10, y=y-1  X; ]* p6 ~  _
    二月 m = 11, y=y-1+ @+ c  o% k) _/ b

    0 }& R* Q3 W$ ?那个4800,是个计算零点,大概在公元前4801年,是和前面所说的那个零点相关的。
    8 f  e4 n2 o+ h" ?& ~$ J然后计算儒略日的公式长是这个样子的:
    . r3 w6 i3 ?- x" g5 Z1 y- m1 A5 t$ l6 I

    / k5 [& h' f( {0 S3 D+ U8 O; @" ?" }! _  p  f# g! K
    这个公式中最巧的部分是 floor((153m+2)/5), 做出的效果嘛,看这个表:; B4 s; K. v) U8 b0 n
    Mar–Jul:31 30 31 30 31Aug–Dec:31 30 31 30 31Jan–Feb:31 284 o0 V6 ?1 c% o! n3 w
    最后面的那个系数,是相对于原点的修正值。原公式算出来的值一般太大,计算中用起来会超过32/64位字长。现在天文计算中一般会选择2000年1月1日为零点,之前有用1900年和1950年的。/ u% Q0 r+ Q4 |: P
    & n- A& O$ G8 l3 J; U2 x7 z. d( `
    从儒略日计算星期几,(JDN+1) mod 7 就好了。. k  U6 d& h9 a9 U. p
    8 n. Z' [! W& j" A$ D. M$ N
    这个公式是怎么来的呢? 1582年,教皇格里高利十三(XIII)发现,那一年的春分是3月11日,和儒略历里规定的日期3月21日差了十天。原因嘛,就是回归年的长度是365.2422,儒略历用的365.25。格十三用上了全部的指头,哦,应该是找了很多XX家之后,下令当年10月4日的后一天是10月15日,同时规定在原先四年一闰的基础上,100的整数倍年不是闰年,但400的整数倍年又是闰年。新的历法改名为格里高利历。0 U+ ~! T; U! ~( a6 _
    1 x0 c! `* \# f# a
    为了计算转换儒略历和格里高利历,一个法国的教会学者Joseph Justus Scaliger给出了这个公式。“儒略日”中的儒略,是他老爸的名字。6 S. n8 C8 T, e9 \" n" |! R
    - M2 k) H  N6 I5 s: d
    哦,原来的文献中用的是儒略历日期,要算儒略日是这样的:+ N0 B* h* ~) Z% T

    3 d/ c) m5 t# ]& N9 U: S, a; x
    6 a; I" |0 Q2 B. T6 d
    . p+ {1 M" t# g4 X* c从儒略日转格里高利历,也有一组公式,这里有:
    3 J0 c' @# n9 \0 E' W+ A& |9 b0 P" T6 I
    其实这些偏差,在儒略历启用之前是有人知道的。但是,始皇三十五年的某一天,一个罗马士兵在西西里岛上,拔出刀来,朝一个老人身上刺下去。这一刺,西方的科技文明停滞了一千多年。来自群组: 软件人家

    评分

    参与人数 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的每日心情
    开心
    昨天 01:10
  • 签到天数: 2669 天

    [LV.Master]无

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

    点评

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

    [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的每日心情
    慵懒
    2025-12-4 14:34
  • 签到天数: 2865 天

    [LV.Master]无

    10#
    发表于 2015-2-2 13:52:01 | 只看该作者
    老兵帅客 发表于 2015-2-2 13:091 e. T- h+ K& T1 I) b- F$ d
    看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多 ...
    / F% t" r3 U0 L: x9 L( ~
    试试计算下一千年每年复活节是哪一天,我又得昏过去了。。。哈哈哈。。。
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    11#
    发表于 2015-2-3 01:49:06 | 只看该作者
    老兵帅客 发表于 2015-2-2 13:095 u. e/ i6 C6 d
    看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多 ...
    - O- i. s* N0 A8 ~9 }; T% V3 l
    这个在当年可以用的日期函数还很罕见的时候有用。后来系统本身就提供这些计算了,自然没必要记。9 T; L1 `  o$ D' V

      C: |  r# a9 r2 d: U8 X3 E% K我最早见到也是学BASIC的时候。( r" ^0 S7 q5 k* V2 f6 h0 I
    + [- U+ r( u% L
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    12#
    发表于 2015-2-3 01:53:29 | 只看该作者
    本帖最后由 橡树村 于 2015-2-3 01:55 编辑 2 W$ h( f& b) q6 X$ ^$ {, X
    hotmen 发表于 2015-2-2 11:27
    : I- K: o9 o+ l8 ?: r0 @2 Y能换算干支就更好了。

    ' V" }* G, U, a; m5 x' \$ j% T0 \0 z  V' E: M2 f3 D. \: ~
    计算干支里面的日期不难,时辰是从日期推算的,也不难。
    ' G# c1 r4 w( \' r* x7 p月份是按照年来推算的,说起来简单,难点在于一年以及一个月的开始时间的计算。这个很难有通用公式。不过还是比农历要简单,干支记年实际上是阳历,每年开始于立春,然后每间隔一个节气就换一个月,与农历的月份并不相同。这样只要有了节气的准确时间数据库,干支的问题也就解决了。- ^! T. U: \6 Y' Q

    5 ^: s0 d$ [" J& M3 b2 ]5 g农历复杂在于,这个历法经常被改动,要准确把历史上的某一天与西历进行换算,需要把曾经使用过的历法都考虑进去,这个麻烦就大了去了。而且每个月的开始取决于月亮的朔望,这就更要把历史上月亮的运行轨道都考虑进去了。  g9 C6 O  F  j6 `9 q
    4 }1 h! ~6 j0 \7 g5 L1 ^$ r
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    13#
    发表于 2015-2-3 02:13:12 | 只看该作者
    橡树村 发表于 2015-2-2 12:49
    & m. b% N( V# S3 F, A这个在当年可以用的日期函数还很罕见的时候有用。后来系统本身就提供这些计算了,自然没必要记。& Q" p) F% S4 v- F7 o9 R, S
    + w7 j9 P8 C8 ]- v5 _5 w
    我最早 ...
    ' x0 @. q' T* V
    问题是DOS下面的BASIC已经提供日期函数了啊,程序员何必再用这个?
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    14#
    发表于 2015-2-3 02:21:35 | 只看该作者
    老兵帅客 发表于 2015-2-3 02:13; ]/ d( [& ?; o# e& s
    问题是DOS下面的BASIC已经提供日期函数了啊,程序员何必再用这个?
    - \5 J/ X) j1 a
    不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程,最多弄个日历啥的。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    15#
    发表于 2015-2-3 02:29:31 | 只看该作者
    橡树村 发表于 2015-2-2 13:214 L- N% ]. V+ q1 V
    不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程 ...
    + }1 A# ~. j# p& c  i* A
    我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找出当前日期,然后自己计算闰年。计算闰年的算法很简单的,远比楼主的简单。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    16#
    发表于 2015-2-3 02:29:44 | 只看该作者
    橡树村 发表于 2015-2-2 13:21
    1 o% f8 V0 e; F* Q$ E% P( F: a; H不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程 ...
    0 Y3 p: p# q" N& x- L8 @: N
    我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找出当前日期,然后自己计算闰年。计算闰年的算法很简单的,远比楼主的简单。
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    17#
    发表于 2015-2-3 02:42:02 | 只看该作者
    老兵帅客 发表于 2015-2-3 02:29" f2 n, a  C# y# P( D% D2 I& ?
    我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找 ...

    ; P8 S5 `  K+ t; GTurbo Pascal?
    0 C7 t! e2 q+ N5 h+ U* k7 c% i+ ~+ x/ t8 e, r4 N
    最早PC机带的BASIC函数很少的,和Pascal比不了。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    18#
    发表于 2015-2-3 02:44:42 | 只看该作者
    橡树村 发表于 2015-2-2 13:42* e5 B! X, z% o' K. v
    Turbo Pascal?
    + j( G; ~1 l' E# M2 b* J* _( p
    . C+ z- h& `& e7 `$ m9 b8 F最早PC机带的BASIC函数很少的,和Pascal比不了。

    % D) b) K. z/ k( H不,是标准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: J! M. P  t* t, Y' l4 A- d$ F: @
    不,是标准PASCAL,用的是微软的编译器。我上学的时候还没出turbo pascal呢,后来这东西出来了,拿来一试 ...
    7 q6 a6 ^# n5 ^1 P! V/ v$ Y, g
    Turbo pascal 是83年的,那时候我还不知道计算机长啥样呢。2 o) X; b3 S. b% l8 s9 ~; o: r
    + P! v1 F3 ]( N6 O0 D+ G, O
    我最早是在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:52
    ; a, `1 ?  O6 |# ^5 ?% kTurbo pascal 是83年的,那时候我还不知道计算机长啥样呢。! u- O; f5 F0 H0 j
    & v- p1 t7 K( w* |2 \
    我最早是在Comx35机器上接触的BASIC,84年。 ...

    4 L# I# l0 G9 z  `4 a" j村子老资格啊

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

    GMT+8, 2026-1-19 04:13 , Processed in 0.036650 second(s), 18 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

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