设为首页收藏本站

爱吱声

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

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

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

    [LV.Master]无

    跳转到指定楼层
    楼主
    发表于 2015-2-1 18:10:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本帖最后由 heinsect 于 2015-2-1 18:13 编辑 4 O- y4 a' L8 |0 m3 {
    9 a) t" L3 e( H2 S$ n% r* x
    程序员计算日期是用儒略日的。
    8 U8 V; c) x- X, g, K" A, Y( U
    + \! P' M, Y' ^# M! E儒略日中的儒略和儒略历中的儒略的关系嘛,只是因为儒略日的发明人的爷爷葱白凯撒,给儿子用了大帝的名字。刚好儒略历也用了大帝的名字。
    0 `+ S2 S5 l9 J$ K- e# Z& b  q' L$ k& B
    单用日期的话,儒略日是从某天开始的一个日的整数。两个儒略日的差值就是相差的天数。这样想计算两个日期间的差值,计算星期几就很简单了。至于那个开始日期,儒略日的零点,用起来的时候谁也不关心,我就不讲了。; G* I# J" t: R' ^6 P& {

    + [. q: ^, U2 ]. r  j从格里高利历日期算儒略日(JDN)的公式是这个样子的:2 o+ V- Y5 W2 u. z( s: e  Q  b3 }# g

    # d* e7 L7 o: U+ _, D" K先要改一下年月:
    8 ?0 ~6 v( ^; c: x% ~3 g! `
    8 d, V- Z8 w* m2 S/ ]
    6 a+ q" }6 K( C! V9 `上面这组公式的结果呢,差不多是这个意思:5 D+ y" ?* Z% g; X. w$ a  P7 j
    三月 m = 0, y=y/ B% w& s: E0 J/ `8 V: C4 k& T
    ...( ^0 j2 o* G  e
    十二月 m=9, y=y
    " F/ F( @; A" g, l7 a一月 m = 10, y=y-1
    ( \4 V4 H' [3 f7 G+ t( B8 I* [二月 m = 11, y=y-10 w9 N3 i4 k# w- l8 A5 A! }) V
    3 g( x' i6 i% g
    那个4800,是个计算零点,大概在公元前4801年,是和前面所说的那个零点相关的。3 _- V1 ^2 f7 H
    然后计算儒略日的公式长是这个样子的:! s' T8 a! }: [8 U6 K" }

    # W6 X- L. T' J$ \* b5 O0 h& E3 B

    & Q7 f" H! P0 N0 Q这个公式中最巧的部分是 floor((153m+2)/5), 做出的效果嘛,看这个表:* i& o6 b8 D$ M' b! v
    Mar–Jul:31 30 31 30 31Aug–Dec:31 30 31 30 31Jan–Feb:31 28# G/ x  Q% S+ P' t
    最后面的那个系数,是相对于原点的修正值。原公式算出来的值一般太大,计算中用起来会超过32/64位字长。现在天文计算中一般会选择2000年1月1日为零点,之前有用1900年和1950年的。
      S3 U+ a6 {+ u! v' E9 V( o
    0 O- v0 b* g4 }1 N$ U5 L4 T从儒略日计算星期几,(JDN+1) mod 7 就好了。
    , o) z2 b) }( q! C4 T) K! j+ j
    / l/ \% |# {$ i1 a8 \  f2 J这个公式是怎么来的呢? 1582年,教皇格里高利十三(XIII)发现,那一年的春分是3月11日,和儒略历里规定的日期3月21日差了十天。原因嘛,就是回归年的长度是365.2422,儒略历用的365.25。格十三用上了全部的指头,哦,应该是找了很多XX家之后,下令当年10月4日的后一天是10月15日,同时规定在原先四年一闰的基础上,100的整数倍年不是闰年,但400的整数倍年又是闰年。新的历法改名为格里高利历。
    0 z% n2 x" C; _; o/ y
    + k" {* p% b/ T为了计算转换儒略历和格里高利历,一个法国的教会学者Joseph Justus Scaliger给出了这个公式。“儒略日”中的儒略,是他老爸的名字。/ K$ P) G8 Z/ x  f& ?, c6 s& V
    * ]- H0 J* G+ q4 _8 P
    哦,原来的文献中用的是儒略历日期,要算儒略日是这样的:" Z6 X6 c3 q' G$ K, p) Z7 P
    3 W- _1 E7 u, D( s

    " @% ?* L. W! j% {( p; L% x: {7 e* J7 T* P
    从儒略日转格里高利历,也有一组公式,这里有:+ j7 ~- O2 J9 n
    6 U1 t5 S9 L) {5 z" Y+ `
    其实这些偏差,在儒略历启用之前是有人知道的。但是,始皇三十五年的某一天,一个罗马士兵在西西里岛上,拔出刀来,朝一个老人身上刺下去。这一刺,西方的科技文明停滞了一千多年。来自群组: 软件人家

    评分

    参与人数 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的每日心情
    开心
    2025-4-27 10:47
  • 签到天数: 2650 天

    [LV.Master]无

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

    点评

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

    [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-1-26 07:36
  • 签到天数: 2860 天

    [LV.Master]无

    10#
    发表于 2015-2-2 13:52:01 | 只看该作者
    老兵帅客 发表于 2015-2-2 13:09: C. I6 @) h) }& D: y) E
    看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多 ...
    . {, O0 O: x- j- i1 C% f" l( x, X
    试试计算下一千年每年复活节是哪一天,我又得昏过去了。。。哈哈哈。。。
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    11#
    发表于 2015-2-3 01:49:06 | 只看该作者
    老兵帅客 发表于 2015-2-2 13:09* B8 Q8 b0 D0 Y& m5 G) j# u/ \5 h
    看来俺一定不是程序员了,因为俺从来就没这么复杂地玩过。日期可以从系统函数或者类库中的方法得到,我最多 ...

    ! g4 x, u/ i3 v) B% y2 U0 k# E$ y; _" l这个在当年可以用的日期函数还很罕见的时候有用。后来系统本身就提供这些计算了,自然没必要记。
    1 `* m5 W# W" s; L7 v1 ^0 L
    4 V& ]  y6 I' I我最早见到也是学BASIC的时候。9 ^! ^" ^* R2 I% H
      q' w( g7 P: k  b" f* W, V9 P
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    12#
    发表于 2015-2-3 01:53:29 | 只看该作者
    本帖最后由 橡树村 于 2015-2-3 01:55 编辑 , y8 _! w) _' b: {
    hotmen 发表于 2015-2-2 11:27* R$ ]* T4 g& d" n- k
    能换算干支就更好了。

    & _' U5 M  p# ^; W2 F/ Z  k% I
    7 Y" U% f3 F5 l! u8 i计算干支里面的日期不难,时辰是从日期推算的,也不难。- N  t! H' [9 g9 E4 Z- i
    月份是按照年来推算的,说起来简单,难点在于一年以及一个月的开始时间的计算。这个很难有通用公式。不过还是比农历要简单,干支记年实际上是阳历,每年开始于立春,然后每间隔一个节气就换一个月,与农历的月份并不相同。这样只要有了节气的准确时间数据库,干支的问题也就解决了。8 ]$ l# ]' H! |. Y8 O

    6 `4 `$ |' N) g1 C# M$ P* }农历复杂在于,这个历法经常被改动,要准确把历史上的某一天与西历进行换算,需要把曾经使用过的历法都考虑进去,这个麻烦就大了去了。而且每个月的开始取决于月亮的朔望,这就更要把历史上月亮的运行轨道都考虑进去了。
    ' W* l9 e5 r0 [) p/ ~8 ^4 N( `! J5 s
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    13#
    发表于 2015-2-3 02:13:12 | 只看该作者
    橡树村 发表于 2015-2-2 12:49* H) w6 a2 o8 d* _  M4 h
    这个在当年可以用的日期函数还很罕见的时候有用。后来系统本身就提供这些计算了,自然没必要记。
    * d0 y9 Z" R9 S: h2 n' c
    $ b) V$ D0 f/ j我最早 ...

    6 y9 ]" h$ H4 T) Y; U, }" z问题是DOS下面的BASIC已经提供日期函数了啊,程序员何必再用这个?
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    14#
    发表于 2015-2-3 02:21:35 | 只看该作者
    老兵帅客 发表于 2015-2-3 02:13
    % A5 V+ I7 [9 A8 ^! z# F问题是DOS下面的BASIC已经提供日期函数了啊,程序员何必再用这个?
    # ?) p. D) E+ ^  \+ t
    不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程,最多弄个日历啥的。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    15#
    发表于 2015-2-3 02:29:31 | 只看该作者
    橡树村 发表于 2015-2-2 13:21
    ' i/ ^; o, T9 N+ V/ O7 a2 W9 I不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程 ...

    3 ?* O0 m' ?' w% Z4 H7 L8 H3 A% z9 F我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找出当前日期,然后自己计算闰年。计算闰年的算法很简单的,远比楼主的简单。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    16#
    发表于 2015-2-3 02:29:44 | 只看该作者
    橡树村 发表于 2015-2-2 13:21
    & L0 g* X' z% C/ l* ?; d# n1 E不记得当年BASIC有计算两个日期之间有几天的函数。也许有但从来没用过,当年就没有使用BASIC做过这类编程 ...

    / p! b$ U9 k' F- y2 _) }5 N: i" ?8 D( g7 R我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找出当前日期,然后自己计算闰年。计算闰年的算法很简单的,远比楼主的简单。
  • TA的每日心情
    开心
    2022-12-1 00:01
  • 签到天数: 2488 天

    [LV.Master]无

    17#
    发表于 2015-2-3 02:42:02 | 只看该作者
    老兵帅客 发表于 2015-2-3 02:29
      I, w0 Q6 G6 F6 |$ o& t我当年学PASCAL的时候,一个作业就是编万年历,从你的当前日期开始。因此我们就用PASCAL自带的日期函数找 ...
    2 W9 E9 K1 K' x* D
    Turbo Pascal?
    , l/ L% e) A, T! \7 j* B1 w( Z( L/ U$ A# j% P
    最早PC机带的BASIC函数很少的,和Pascal比不了。
  • TA的每日心情
    开心
    2023-1-5 00:48
  • 签到天数: 2591 天

    [LV.Master]无

    18#
    发表于 2015-2-3 02:44:42 | 只看该作者
    橡树村 发表于 2015-2-2 13:42+ i! \. g0 K; n$ Z
    Turbo Pascal?
    : m8 E. B! V- E( X+ Q  c3 J" ]! w8 [1 K: t# V* Q
    最早PC机带的BASIC函数很少的,和Pascal比不了。

    6 Y; G2 ^7 a6 A& X, u$ U不,是标准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
    * ^2 l( w3 X1 G7 f3 s0 n不,是标准PASCAL,用的是微软的编译器。我上学的时候还没出turbo pascal呢,后来这东西出来了,拿来一试 ...
    0 v: k9 |8 n% f4 G2 ^
    Turbo pascal 是83年的,那时候我还不知道计算机长啥样呢。. i1 W2 }$ A, R9 F5 r, Y

    * t! k6 n2 z- b; _我最早是在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
    6 D- L0 h# c$ @. p' J) wTurbo pascal 是83年的,那时候我还不知道计算机长啥样呢。3 m" |1 [" D2 |! f) y
    0 P0 a( g- _7 R0 \8 p! x# t' k
    我最早是在Comx35机器上接触的BASIC,84年。 ...
    " y7 |) v& Y  T/ c3 r3 ]
    村子老资格啊

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

    GMT+8, 2025-5-23 08:19 , Processed in 0.054014 second(s), 24 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

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