ちょっと、2月のカレンダーと「14日の土曜日」ネタがらみで、
そういや、2月のカレンダーが823年ぶりというガセ、ゆうきまさみファンならすぐ見抜けたはず…
究極超人あ〜る 8 (少年サンデーコミックス) http://t.co/GKKHtUc5DY
1987/06
第80話「14日の土曜日」 pic.twitter.com/vD0WISAjhS
— 風柳 (@furyutei) 2015, 2月 13
のようなことをつぶやきたいな、と思って、念のため調べていたら、いつの間にかFreeBSDのncalコマンドのバグなのかも?と思われるものを見つけてしまった、という話。
いや、我ながら何を言っているのかわかりませんが…。
■ 経緯
◇ 13日の金曜日よりも14日の土曜日が重要なクラスタより
- タイムライン上に「そういえば13日の金曜日」のようなツイートがちらちら
- すると「14日は土曜日ではないか!」と反応しはじめる、偏った人々(ゆうきまさみフォロワーの方ね)
◇ 2月で「14日の土曜日」だった年を調べたところ…
『あ〜るのバレンタイン話は、確か1987年だったよなぁ』
$ cal 2 1987 2月 1987 日 月 火 水 木 金 土 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
『うんうん。えーと、今年はそれから何回目?ついでに西暦1年から調べてみるか』
$ python >>> import calendar >>> all, counter = 0, 0 >>> for year in range(1, 1+2015): ... if calendar.weekday(year, 2, 14) == 5: ... all += 1 ... if 1987 < year: counter += 1 ... print year ... 4 9 15 :(中略) 1750 1756 :(中略) 1981 1987 1998 2004 2009 2015 >>> print all, counter 288 4 >>>
『ほぉ、西暦4年もそうだったのか』
$ cal 2 4 2月 4 日 月 火 水 木 金 土 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
『あ、あれれ……?』
:
(中略)
:
$ cal 2 1750 2月 1750 日 月 火 水 木 金 土 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
『んん…?』
― 間 ―
$ cal 2 1756 2月 1756 日 月 火 水 木 金 土 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
『あ、これはちゃんと14日の土曜日になってるな。このあたりが境目、か……?』
◇ 原因は?
$ man cal CAL(1) FreeBSD General Commands Manual CAL(1) NAME cal, ncal ― displays a calendar and the date of Easter (中略) -s country_code Assume the switch from Julian to Gregorian Calendar at the date associated with the country_code. If not specified, ncal tries to guess the switch date from the local environment or falls back to September 2, 1752. This was when Great Britain and her colonies switched to the Gregorian Calendar.
なる程、デフォルトだと、イギリスがグレゴリオ暦を採用した1752年9月14日以降がグレゴリオ暦表示で、それ以前はユリウス暦表示なのね。
$ cal 9 1752 9月 1752 日 月 火 水 木 金 土 1 2 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
ほうほう。グレゴリオ暦での1752年9月13日はユリウス暦1752年9月2日なので、こうなるのね。
◇ 国名コードを指定するとどうなる?
これ、他の国だとどうなるんだろう?
ISO 3166-1 - Wikipedia
コマンドの -s オプションで指定できる国名コード(country_code)は二字のもの、ただし、網羅されているわけではない。
そもそも、イタリア(1582年10月15日グレゴリオ暦制定)だと?
《参考資料》ユリウス暦からグレゴリオ暦への切り替え
みんなの知識【ちょっと便利帳】 - その曜日は何日? 各年・各月の曜日を調べる - 西暦と月を設定し、各曜日の日付を一覧表示
・1582年にローマ法王グレゴリオ13世がユリウス暦からグレゴリオ暦への転換を宣言したことにより、この時期にユリウス暦からグレゴリオ暦への切り替えが行われた国があります。
・カトリック国のイタリア、スペインなどでは1582年10月に切り替えが行われ、1582年10月4日の翌日が10月15日になり、1582年10月5日から10月14日までは存在しません。
$ cal -s IT 10 1582 Usage: cal [general options] [-hjy] [[month] year] cal [general options] [-hj] [-m month] [year] ncal [general options] [-hJjpwy] [-s country_code] [[month] year] ncal [general options] [-hJeo] [year] General options: [-NC3] [-A months] [-B months] For debug the highlighting: [-H yyyy-mm-dd] [-d yyyy-mm]
あ、-s オプションは ncal だけか。
$ ncal -s IT 10 1582 10月 1582 月 1 18 25 火 2 19 26 水 3 20 27 木 4 21 28 金 15 22 29 土 16 23 30 日 17 24 31
うん、確かに10/15を境に切り替わっているな。
じゃあ、日本だとどうなの?
・1873年1月1日に当たる明治5年12月3日(旧暦)を明治6年1月1日(新暦)とする太陽暦への改暦(明治改暦)。
グレゴリオ暦 - Wikipedia
$ ncal -s JP -A 1 12 1872 12月 1872 1月 1873 月 4 11 18 25 1 8 15 22 29 火 5 12 19 26 2 9 16 23 30 水 6 13 20 27 3 10 17 24 31 木 7 14 21 28 4 11 18 25 金 1 8 15 22 29 5 12 19 26 土 2 9 16 23 30 6 13 20 27 日 3 10 17 24 31 7 14 21 28
ん?日付は連続しているし……
$ ncal -s IT -A 1 12 1872 12月 1872 1月 1873 月 2 9 16 23 30 6 13 20 27 火 3 10 17 24 31 7 14 21 28 水 4 11 18 25 1 8 15 22 29 木 5 12 19 26 2 9 16 23 30 金 6 13 20 27 3 10 17 24 31 土 7 14 21 28 4 11 18 25 日 1 8 15 22 29 5 12 19 26
イタリアの暦とも違っている、ということは、このあたりはまだユリウス暦で表示されている、ということ?
◇ ncalでは、日本はいつグレゴリオ暦に切り替えたことになっているのか?
$ ncal -s JP -A 1 12 1918 12月 1918 1月 1919 月 3 10 17 6 13 20 27 火 4 11 18 7 14 21 28 水 5 12 1 8 15 22 29 木 6 13 2 9 16 23 30 金 7 14 3 10 17 24 31 土 1 8 15 4 11 18 25 日 2 9 16 5 12 19 26
は、はい……?
1919年1月1日から切り替えたことになっているのか……なぜ???
■ 結論(暫定)
結局、自分が調べた範囲では理由がわからず、単純なプログラム上の登録ミスではないか? と考えている。
実は深い理由があるのかも……ご存知の方、教えてください。
[base] Contents of /head/usr.bin/ncal/ncal.c
69 /* The switches from Julian to Gregorian in some countries */ 70 static struct djswitch { 71 const char *cc; /* Country code according to ISO 3166 */ 72 const char *nm; /* Name of country */ 73 date dt; /* Last day of Julian calendar */ 74 } switches[] = { 75 {"AL", "Albania", {1912, 11, 30}}, 76 {"AT", "Austria", {1583, 10, 5}},
のように、ISO 3166の国名コード(2文字)毎にユリウス暦→グレゴリオ暦に移り変わった日付の定義がなされているが、そのうち、日本(JP)用の定義が違っているのではないか、と。
$ diff -c ncal.c.r241737 ./ncal.c *** ncal.c.r241737 2015-02-13 02:24:25.000000000 +0900 --- ./ncal.c 2015-02-13 02:26:03.000000000 +0900 *************** *** 91,97 **** {"HU", "Hungary", {1587, 10, 21}}, {"IS", "Iceland", {1700, 11, 16}}, {"IT", "Italy", {1582, 10, 4}}, ! {"JP", "Japan", {1918, 12, 18}}, {"LI", "Lithuania", {1918, 2, 1}}, {"LN", "Latin", {9999, 05, 31}}, {"LU", "Luxembourg", {1582, 12, 14}}, --- 91,97 ---- {"HU", "Hungary", {1587, 10, 21}}, {"IS", "Iceland", {1700, 11, 16}}, {"IT", "Italy", {1582, 10, 4}}, ! {"JP", "Japan", {1872, 12, 19}}, {"LI", "Lithuania", {1918, 2, 1}}, {"LN", "Latin", {9999, 05, 31}}, {"LU", "Luxembourg", {1582, 12, 14}},
$ # 改修版の実行結果 $ ./ncal -s JP -A 1 12 1872 12月 1872 1月 1873 月 4 11 18 6 13 20 27 火 5 12 19 7 14 21 28 水 6 13 1 8 15 22 29 木 7 14 2 9 16 23 30 金 1 8 15 3 10 17 24 31 土 2 9 16 4 11 18 25 日 3 10 17 5 12 19 26
◇ 注釈
そもそも日本の場合、べつにグレゴリオ暦の前にユリウス暦を使っていたわけではないので、定義するのはナンセンス、という話はある。
その上で、元のソースコード中で「グレゴリオ暦1919年1月1日」(厳密にはその前日に当たるユリウス暦1918年12月18日)が登録されている根拠もよくわからず、まだこれよりは、明治改暦が実施された「グレゴリオ暦1873年1月1日」(同1872年12月19日)を登録した方がもっともらしいのではないか、と考える次第。
■ 補足等
◇ ncal のバグについて
そもそもncal中の国別のユリウス暦→グレゴリオ暦切替日定義は、日本以外に関しても信頼できるかどうかは怪しい、のかも。
ncal(1)
BUGS
https://www.freebsd.org/cgi/man.cgi?query=ncal&sektion=1&manpath=FreeBSD+6.0-RELEASE
The assignment of Julian--Gregorian switching dates to country codes is
historically naive for many countries.
$ ncal -p AL Albania 1912-11-30 IT Italy 1582-10-04 AT Austria 1583-10-05 *JP Japan 1918-12-18 AU Australia 1752-09-02 LI Lithuania 1918-02-01 BE Belgium 1582-12-14 LN Latin 9999-05-31 BG Bulgaria 1916-03-18 LU Luxembourg 1582-12-14 CA Canada 1752-09-02 LV Latvia 1918-02-01 CH Switzerland 1655-02-28 NL Netherlands 1582-12-14 CN China 1911-12-18 NO Norway 1700-02-18 CZ Czech Republic 1584-01-06 PL Poland 1582-10-04 DE Germany 1700-02-18 PT Portugal 1582-10-04 DK Denmark 1700-02-18 RO Romania 1919-03-31 ES Spain 1582-10-04 RU Russia 1918-01-31 FI Finland 1753-02-17 SI Slovenia 1919-03-04 FR France 1582-12-09 SW Sweden 1753-02-17 GB United Kingdom 1752-09-02 TR Turkey 1926-12-18 GR Greece 1924-03-09 US United States 1752-09-02 HU Hungary 1587-10-21 YU Yugoslavia 1919-03-04 IS Iceland 1700-11-16
※ラテン世界の9999年
$ ncal -s LN 9999 9999 1月 2月 3月 4月 月 1 8 15 22 29 5 12 19 26 5 12 19 26 2 9 16 23 30 火 2 9 16 23 30 6 13 20 27 6 13 20 27 3 10 17 24 水 3 10 17 24 31 7 14 21 28 7 14 21 28 4 11 18 25 木 4 11 18 25 1 8 15 22 1 8 15 22 29 5 12 19 26 金 5 12 19 26 2 9 16 23 2 9 16 23 30 6 13 20 27 土 6 13 20 27 3 10 17 24 3 10 17 24 31 7 14 21 28 日 7 14 21 28 4 11 18 25 4 11 18 25 1 8 15 22 29 5月 6月 7月 8月 月 7 14 21 28 16 23 30 火 1 8 15 22 29 17 24 31 水 2 9 16 23 30 18 25 木 3 10 17 24 31 19 26 金 4 11 18 25 13 20 27 土 5 12 19 26 14 21 28 日 6 13 20 27 15 22 29 9月 10月 11月 12月 月 6 13 20 27 4 11 18 25 1 8 15 22 29 6 13 20 27 火 7 14 21 28 5 12 19 26 2 9 16 23 30 7 14 21 28 水 1 8 15 22 29 6 13 20 27 3 10 17 24 1 8 15 22 29 木 2 9 16 23 30 7 14 21 28 4 11 18 25 2 9 16 23 30 金 3 10 17 24 1 8 15 22 29 5 12 19 26 3 10 17 24 31 土 4 11 18 25 2 9 16 23 30 6 13 20 27 4 11 18 25 日 5 12 19 26 3 10 17 24 31 7 14 21 28 5 12 19 26
◇ 覚書
- FreeBSD の cal コマンドは ncal コマンドのエイリアス
バイナリレベルで同一。コマンド名で判別し、ncalの -C オプション相当の表示をしている模様。
◇ 愚痴
というかそもそも、「とある年月を境にしてユリウス暦とグレゴリオ暦が切り替えられ、かつ、一見して(表示結果では)それとわからない」なんて仕様のカレンダー自体、やめて欲しいと思うのは自分だけ?
「デフォルトでグレゴリオ暦換算のカレンダーを表示、オプションでユリウス暦換算でも表示可能だよ」でええやん…。