みなさんご存知サマーウォーズで、けんじ君となつき先輩が曽祖母の誕生会のための電車で移動中、けんじ君がなつき先輩の誕生日から曜日を当てるシーンがある。
僕が初めてサマーウォーズを見たのが、中学生(おそらく)の時で「え?なんでわかるん?すごくない?」となったのを今でも覚えている。さらに、けんじ君が「モジュロ演算ってのを使って!」と言っており、「あ、この人やばいわ。」となったのも覚えている。
なぜか今更になって、「あれどうやったんやろ?」と思ったので、調べて実装した。
ツェラーの公式
「日付」「曜日」「特定」などでググると簡単に公式が出て来た。ツェラーの公式というもので、年・月・日から曜日がわかるらしい。
実装
数式ははmarkdownでうまく書けなかったので、Rubyで実装した。色々な形があるが、その中の一例。
year = 2019 # <= 西暦
month = 12 # <= 月
day = 10 # <= 日
# ツェラーの公式
def Zeller(year, month, day)
weeks = ["Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
remainder = (day + (month + 1) * 26 / 10 + year % 100 + (year % 100) / 4 + (year / 100) / 4 - 2 * (year / 100) ) % 7
weeks[remainder]
end
p Zeller(year, month, day)
Tuesday
正しくできた。
土曜日が基準になっているようだが、7で割る前の数を調整すれば、日曜日・月曜日から始まる配列でも対応できる。
公式がわかったから曜日すぐわかるやん!とはならず、計算するには電卓を叩きたくなる。
曜日の基準っていつ?
ここで素朴な疑問として、曜日の始まりって何曜日?が出て来た。
仮説 西暦1年1月1日って日曜日??
実際にツェラーの公式で計算すると、Sutudayらしい。。微妙な。。。
追記
wikipediaに以下の説明があった.
西暦4年3月1日以前は閏年の規則が異なるので、ユリウス暦の公式も適用できない。
ということで、西暦1年にはこの公式は利用できなかった。。。
結果
調べるとwikipediaに以下の説明があった。
日付から曜日を特定するには、ある1日についてそれが何曜日かを決めておく必要がある。
これは古代からデファクトスタンダード(事実上の標準)として暗黙裏に広く認められ使われていたが、あらためてISO 8601で「2000年1月1日を土曜日とする」と定義された。
日本ではJIS X 0301がそれに従っている。
結構最近定義されたんやな。。
2000年を基準として、公式をもっと簡約化できそうな気もする。
まとめ
けんじ君はすごい。
「よろしくお願いしまぁぁぁぁぁす!!!!!!」のシーンでRSA暗号暗算で解読することに比べたら朝飯前なのか。。。