解析xlsx發(fā)現(xiàn)關(guān)于閏年有趣的事情

[excel] [xlsx] [閏年計(jì)算] [日期計(jì)算]

起因

最近在使用 golang 解析 xlsx 文件完成一些功能草慧,發(fā)現(xiàn)使用 excelize 庫解析日期類型的值時(shí)稿静,獲取到的是一個(gè)數(shù)字假夺。

Excel中顯示 2012/12/1烟逊,excelize 解析獲得 41244

怎么把獲得的數(shù)字轉(zhuǎn)換成日期類型,好做后面的操作呢。經(jīng)過搜索獲得了解決方案:

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
}

執(zhí)行查看

打印結(jié)果是正確的边器,但是為什么要將天數(shù)減2才能獲取的正確的時(shí)間?

關(guān)于閏年的計(jì)算

Excel 日期的存儲(chǔ)

首先托修,需要知道的是為什么日期類型會(huì)變成數(shù)字忘巧,這個(gè)數(shù)字代表什么?

Excel 將日期存儲(chǔ)為數(shù)字诀黍,這個(gè)數(shù)字是從 1900/1/1 起經(jīng)過的天數(shù)袋坑。1900/1/1 日是第1天。

如果是這樣眯勾,應(yīng)該 days - 1 就可以了枣宫,為什么要 days - 2 呢?

如果想要揭開這個(gè)謎團(tuán)吃环,就需要先回答兩個(gè)問題:

  1. 閏年如何計(jì)算也颤?
  2. 1900年是閏年么?

如何計(jì)算閏年

關(guān)于閏年如何計(jì)算郁轻。大家一定覺得很簡單:

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

那么,因?yàn)?1900 % 4 == 0 好唯,所以 1900 年是閏年啊竭沫。

如果你這么想,那就能體會(huì)為什么出現(xiàn)上面的問題了骑篙。

首先蜕提,1900年不是閏年。翻了大半天日歷進(jìn)行確認(rèn):

1900年2月

其次靶端,閏年的計(jì)算公式不是簡單地 “可以被4整除”谎势。閏年的計(jì)算:

非整百年份:能被4整除的是閏年。
整百年份:能被400整除的是閏年杨名。
閏年的計(jì)算脏榆,歸結(jié)起來就是通常說的:四年一閏;百年不閏台谍,四百年再閏须喂。

看到這個(gè)計(jì)算公式時(shí),我也是驚到了趁蕊,因?yàn)橛∠笾心髡郏恢币詠矶紱]有注意過百年的處理?xiàng)l件。

由于1900 年是百年介衔,且不能被 400 整除恨胚,所以 1900 年不是閏年。

Excel的bug

Excel使用 1900日期系統(tǒng)炎咖,使用從1900/1/1日開始經(jīng)過的天數(shù)表示日期赃泡。

但是,Excel錯(cuò)誤地假定 1900 年是閏年乘盼。所以在 Excel 有一個(gè)錯(cuò)誤的日期 1900/2/29升熊,這個(gè)日期時(shí)不存在的,所以從 1900/3/1 之后绸栅,每個(gè)日期的表示就多了1天级野。

這就是 days - 2 的原因,需要減去多余的 1900/3/1粹胯。不過 1900/2/28 及其之前的日期計(jì)算就不需要多減去額外的1天了蓖柔。

對于這個(gè)bug辰企,官方是這么解釋的:

微軟關(guān)于1900問題的回答

簡短的說,就是修改這個(gè)bug會(huì)耗費(fèi)大量的時(shí)間况鸣,并產(chǎn)生兼容問題牢贸,而這個(gè)問題本身產(chǎn)生的問題有限,所以不做修改镐捧。

而且為了計(jì)算方便潜索,Excel 保留了 1900/1/0 這個(gè)日期。

有趣的1582年

在查閱資料的時(shí)候懂酱,發(fā)現(xiàn)了另外一個(gè)有意思的故事:

需要注意的是竹习,公歷是根據(jù)羅馬人的“儒略歷”改編而成的。由于當(dāng)時(shí)沒有了解到每年要多算出0.0078天的問題列牺,從公元前46年到16世紀(jì)整陌,一共累計(jì)多出了10天。為此昔园,當(dāng)時(shí)的教皇格列高利十三世蔓榄,將1582年10月5日改為10月15日,并開始了新的閏年規(guī)定默刚。即規(guī)定公歷年份是整百數(shù)的甥郑,必須是400的倍數(shù)才是閏年,不是400的倍數(shù)的年份就是平年荤西。
— 摘自百度百科

1582年澜搅,為了更正閏年的計(jì)算,整整少了10天邪锌。我又翻了大半天日歷進(jìn)行確認(rèn):

1582年10月

結(jié)語

經(jīng)過這一趟操作下來勉躺,有兩個(gè)感受:

  1. 方案的確定,一定是有取舍的觅丰。發(fā)生問題后饵溅,需要確定影響的范圍,如果修改帶來的弊遠(yuǎn)大于利妇萄,且問題影響的范圍較小蜕企,那么可以舍小取大。問題的解決方式不是一成不變的冠句,問題也不是一定必須修改的轻掩,需要根據(jù)情況而定。
  2. 誤差是不可避免的懦底,需要?jiǎng)討B(tài)的更正唇牧、調(diào)整。但是解決問題還要限定問題的邊界,先處理力所能及范圍內(nèi)的丐重。正如閏年的計(jì)算也不是一成不變的腔召,但是對于幾千年之后的計(jì)算誤差,目前也沒法精確給出弥臼,所以還是解決好幾百年內(nèi)的問題吧:

    由于地球的自轉(zhuǎn)速度逐漸降低宴咧,而公轉(zhuǎn)速度則相對更加穩(wěn)定根灯,所以上述的系統(tǒng)經(jīng)過更長的周期也會(huì)發(fā)生微小的誤差径缅。據(jù)計(jì)算,每8000年會(huì)有一天的誤差烙肺,所以英國的天文學(xué)家約翰·赫歇耳提議:公元4000年為平年纳猪,以此類推,公元12000年桃笙、20000年也是平年氏堤。但此提議從未被正式采納。原因是到了4000年搏明,地球自轉(zhuǎn)的精確速度并非如今可以預(yù)測鼠锈,所以屆時(shí)參照真實(shí)數(shù)據(jù)方可做出判斷。因此星著,在長遠(yuǎn)的將來购笆,針對閏年的微小調(diào)整應(yīng)該不是由預(yù)定的系統(tǒng)決定,而是隨時(shí)不定性的虚循。

參考

  1. Excel 錯(cuò)誤地假定 1900 年是閏年
  2. Leap year problem
  3. 1582年10月為什么少了10天同欠?
  4. 百度百科:閏年
  5. 為什么公歷 1900 年不是閏年?
  6. Wikipedia:閏年.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末横缔,一起剝皮案震驚了整個(gè)濱河市铺遂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌茎刚,老刑警劉巖襟锐,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異膛锭,居然都是意外死亡粮坞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門泉沾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捞蚂,“玉大人,你說我怎么就攤上這事跷究⌒昭福” “怎么了聂示?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長纵竖。 經(jīng)常有香客問我墓造,道長,這世上最難降的妖魔是什么解寝? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任扩然,我火速辦了婚禮,結(jié)果婚禮上聋伦,老公的妹妹穿的比我還像新娘夫偶。我一直安慰自己,他們只是感情好觉增,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布兵拢。 她就那樣靜靜地躺著,像睡著了一般逾礁。 火紅的嫁衣襯著肌膚如雪说铃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天嘹履,我揣著相機(jī)與錄音腻扇,去河邊找鬼。 笑死砾嫉,一個(gè)胖子當(dāng)著我的面吹牛幼苛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播焰枢,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼蚓峦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了济锄?” 一聲冷哼從身側(cè)響起暑椰,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荐绝,沒想到半個(gè)月后一汽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡低滩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年召夹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恕沫。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡监憎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婶溯,到底是詐尸還是另有隱情鲸阔,我是刑警寧澤偷霉,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站褐筛,受9級(jí)特大地震影響类少,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜渔扎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一硫狞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧晃痴,春花似錦残吩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽定罢。三九已至笤虫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間祖凫,已是汗流浹背琼蚯。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惠况,地道東北人遭庶。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像稠屠,于是被迫代替她去往敵國和親峦睡。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容