美文网首页
解析xlsx发现关于闰年有趣的事情

解析xlsx发现关于闰年有趣的事情

作者: 啊阿伟啊 | 来源:发表于2023-04-05 21:18 被阅读0次

    [excel] [xlsx] [闰年计算] [日期计算]

    起因

    最近在使用 golang 解析 xlsx 文件完成一些功能,发现使用 excelize 库解析日期类型的值时,获取到的是一个数字。

    Excel中显示 2012/12/1,excelize 解析获得 41244

    怎么把获得的数字转换成日期类型,好做后面的操作呢。经过搜索获得了解决方案:

    import (
        "fmt"
        "time"
    )
    
    func main() {
        days := 41244
        date := time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC).AddDate(0, 0, days-2)
    
        fmt.Println(date)  // 2012-12-01 00:00:00 +0000 UTC
    }
    

    执行查看

    打印结果是正确的,但是为什么要将天数减2才能获取的正确的时间?

    关于闰年的计算

    Excel 日期的存储

    首先,需要知道的是为什么日期类型会变成数字,这个数字代表什么?

    Excel 将日期存储为数字,这个数字是从 1900/1/1 起经过的天数。1900/1/1 日是第1天。

    如果是这样,应该 days - 1 就可以了,为什么要 days - 2 呢?

    如果想要揭开这个谜团,就需要先回答两个问题:

    1. 闰年如何计算?
    2. 1900年是闰年么?

    如何计算闰年

    关于闰年如何计算。大家一定觉得很简单:

    可以被4整除的年份,比如大家最熟悉的年份:2008

    那么,因为 1900 % 4 == 0 ,所以 1900 年是闰年啊。

    如果你这么想,那就能体会为什么出现上面的问题了。

    首先,1900年不是闰年。翻了大半天日历进行确认:

    1900年2月

    其次,闰年的计算公式不是简单地 “可以被4整除”。闰年的计算:

    非整百年份:能被4整除的是闰年。
    整百年份:能被400整除的是闰年。
    闰年的计算,归结起来就是通常说的:四年一闰;百年不闰,四百年再闰。

    看到这个计算公式时,我也是惊到了,因为印象中,一直以来都没有注意过百年的处理条件。

    由于1900 年是百年,且不能被 400 整除,所以 1900 年不是闰年。

    Excel的bug

    Excel使用 1900日期系统,使用从1900/1/1日开始经过的天数表示日期。

    但是,Excel错误地假定 1900 年是闰年。所以在 Excel 有一个错误的日期 1900/2/29,这个日期时不存在的,所以从 1900/3/1 之后,每个日期的表示就多了1天。

    这就是 days - 2 的原因,需要减去多余的 1900/3/1。不过 1900/2/28 及其之前的日期计算就不需要多减去额外的1天了。

    对于这个bug,官方是这么解释的:

    微软关于1900问题的回答

    简短的说,就是修改这个bug会耗费大量的时间,并产生兼容问题,而这个问题本身产生的问题有限,所以不做修改。

    而且为了计算方便,Excel 保留了 1900/1/0 这个日期。

    有趣的1582年

    在查阅资料的时候,发现了另外一个有意思的故事:

    需要注意的是,公历是根据罗马人的“儒略历”改编而成的。由于当时没有了解到每年要多算出0.0078天的问题,从公元前46年到16世纪,一共累计多出了10天。为此,当时的教皇格列高利十三世,将1582年10月5日改为10月15日,并开始了新的闰年规定。即规定公历年份是整百数的,必须是400的倍数才是闰年,不是400的倍数的年份就是平年。
    — 摘自百度百科

    1582年,为了更正闰年的计算,整整少了10天。我又翻了大半天日历进行确认:

    1582年10月

    结语

    经过这一趟操作下来,有两个感受:

    1. 方案的确定,一定是有取舍的。发生问题后,需要确定影响的范围,如果修改带来的弊远大于利,且问题影响的范围较小,那么可以舍小取大。问题的解决方式不是一成不变的,问题也不是一定必须修改的,需要根据情况而定。
    2. 误差是不可避免的,需要动态的更正、调整。但是解决问题还要限定问题的边界,先处理力所能及范围内的。正如闰年的计算也不是一成不变的,但是对于几千年之后的计算误差,目前也没法精确给出,所以还是解决好几百年内的问题吧:

      由于地球的自转速度逐渐降低,而公转速度则相对更加稳定,所以上述的系统经过更长的周期也会发生微小的误差。据计算,每8000年会有一天的误差,所以英国的天文学家约翰·赫歇耳提议:公元4000年为平年,以此类推,公元12000年、20000年也是平年。但此提议从未被正式采纳。原因是到了4000年,地球自转的精确速度并非如今可以预测,所以届时参照真实数据方可做出判断。因此,在长远的将来,针对闰年的微小调整应该不是由预定的系统决定,而是随时不定性的。

    参考

    1. Excel 错误地假定 1900 年是闰年
    2. Leap year problem
    3. 1582年10月为什么少了10天?
    4. 百度百科:闰年
    5. 为什么公历 1900 年不是闰年?
    6. Wikipedia:闰年.

    相关文章

      网友评论

          本文标题:解析xlsx发现关于闰年有趣的事情

          本文链接:https://www.haomeiwen.com/subject/hdhyddtx.html