method_missing(*)

(自分が知る限りで)最古のカレンダーソフトウェア: cal

2024-12-07 (Sat)

これは「タイムラボ Advent Calendar 2024」の 7 日目の記事です。 https://adventar.org/calendars/10585

はじめに

前回 に引き続いて、今年初の投稿です

今年も、業務委託で一緒にお仕事をさせていただいている 株式会社タイムラボ のアドベントカレンダーに参加することになりました!

タイムラボにはエンジニアとして参画しており、フロントエンドとバックエンドを担当しています!

今回、色々何を書くか悩んだのですが、普段カレンダーのアプリケーション開発に携わっている者として知っておくべき、自分が知っている中で最古カレンダーソフトウェア cal コマンドを紹介したいと思います!

なるべくエンジニア以外の方も読めるように、噛み砕いて説明していますので、最後まで読んでいただけると嬉しいです!

なお、筆者は MacOS を利用しているので、今回の記事では GNU 版ではなく、BSD(FreeBSD)版を取り扱います

cal コマンドとは

cal コマンドは、いわゆる Linux コマンドの一種で、ターミナル上にカレンダーを表示するコマンドです。

引数を何も渡さずに実行すると、今月のカレンダーを表示します。

$ cal
      12月 2024
日 月 火 水 木 金 土
 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 30 31

その歴史は古く、man コマンド(コマンドのマニュアルを表示するコマンド)の HISTORY を確認すると、

A cal command appeared in Version 1 AT&T UNIX.

と記載があるので、1971 年頃(半世紀以上前)に登場したことが分かります。

なお、cal を更に拡張した、後発の ncal コマンドも存在します。 こちらは cal よりもオプションが多いのに加え、デフォルトの月の表示形式が縦向きになっています。

$ ncal
    12月 20242  9 16 23 303 10 17 24 314 11 18 255 12 19 266 13 20 277 14 21 281  8 15 22 29

これらのコマンドは柔軟に切り替えることができ、cal-N オプションを付けると ncal に、逆に ncal-C オプションを付けると cal に切り替えることができます。

$ cal -N
    12月 20242  9 16 23 303 10 17 24 314 11 18 255 12 19 266 13 20 277 14 21 281  8 15 22 29

$ ncal -C
      12月 2024
日 月 火 水 木 金 土
 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 30 31

また、これは cal コマンドだけ特殊なのですが、少なくとも 1 つの文字を大文字にして実行すると、ncal に切り替わります

$ Cal
    12月 20242  9 16 23 303 10 17 24 314 11 18 255 12 19 266 13 20 277 14 21 281  8 15 22 29

様々なオプション

cal には様々なオプションが存在しますが、ここでは一部のみを紹介します。

ぜひこの記事を読んでいる方もターミナルを立ち上げて、実際に実行してみると面白いと思います(MacOS の場合はデフォルトでインストールされてます)!

ある年のカレンダーを表示する

cal コマンドに直接数字(1 ~ 9999)を渡すと、その年のカレンダーを表示します。

たとえば、$ cal 1$ cal -y 1)を実行すると、西暦 1 年のカレンダーが表示されます。

年は -y オプションで渡すことも可能です。

(場所を取るので出力結果は省略します…)

ある年月のカレンダーを表示する

cal に 2 つの数字を直接渡すと、1 つ目の数字を月、2 つ目の数字を年とするカレンダーを表示します。

$ cal 2 1994
      2月 1994
日 月 火 水 木 金 土
       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

月は -m オプションで渡すことが可能なため、$ cal -m 2 1994を実行しても、上記の結果を得ることができます。

ただし、-y-m を同時に利用することはできません。

$ cal -m 2 -y 1994
cal: -y together with -m is not supported.

先月と次月のカレンダーも一緒に表示する

-3 オプションをつけると、先月と今月、次月の 3 つのカレンダーをまとめて表示することができます。

$ cal -3
      11月 2024              12月 2024              1月 2025
日 月 火 水 木 金 土  日 月 火 水 木 金 土  日 月 火 水 木 金 土
                1  2   1  2  3  4  5  6  7            1  2  3  4
 3  4  5  6  7  8  9   8  9 10 11 12 13 14   5  6  7  8  9 10 11
10 11 12 13 14 15 16  15 16 17 18 19 20 21  12 13 14 15 16 17 18
17 18 19 20 21 22 23  22 23 24 25 26 27 28  19 20 21 22 23 24 25
24 25 26 27 28 29 30  29 30 31

現在の月の後(前)に続く月数を指定して表示

-A オプションに数字を渡すと、現在の月に続く指定した個数分の月が表示されます。

$ cal -A 1
      12月 2024              1月 2025
日 月 火 水 木 金 土  日 月 火 水 木 金 土
 1  2  3  4  5  6  7            1  2  3  4
 8  9 10 11 12 13 14   5  6  7  8  9 10 11
15 16 17 18 19 20 21  12 13 14 15 16 17 18
22 23 24 25 26 27 28  19 20 21 22 23 24 25
29 30 31              26 27 28 29 30 31

同様に -B オプションに数字を渡すと、現在の月の前の指定した個数分の月が表示されます。

$ cal -B 1
      11月 2024              12月 2024
日 月 火 水 木 金 土  日 月 火 水 木 金 土
                1  2   1  2  3  4  5  6  7
 3  4  5  6  7  8  9   8  9 10 11 12 13 14
10 11 12 13 14 15 16  15 16 17 18 19 20 21
17 18 19 20 21 22 23  22 23 24 25 26 27 28
24 25 26 27 28 29 30  29 30 31

これらのオプションは組み合わせることもできるため、-A-B にそれぞれ 1 を指定すると、-3 を指定した場合と同じ結果を得ることができます。

$ cal -A 1 -B 1
      11月 2024              12月 2024              1月 2025
日 月 火 水 木 金 土  日 月 火 水 木 金 土  日 月 火 水 木 金 土
                1  2   1  2  3  4  5  6  7            1  2  3  4
 3  4  5  6  7  8  9   8  9 10 11 12 13 14   5  6  7  8  9 10 11
10 11 12 13 14 15 16  15 16 17 18 19 20 21  12 13 14 15 16 17 18
17 18 19 20 21 22 23  22 23 24 25 26 27 28  19 20 21 22 23 24 25
24 25 26 27 28 29 30  29 30 31              26 27 28 29 30 31

グレゴリオ暦への切り替えの考慮

話は変わりますが、現在我々が使っている西暦は グレゴリオ暦 であり、1582 年 10 月にローマ教皇 グレゴリウス 13 世 によって導入されたものです。

導入された意図としては、それまで採用されていた ユリウス暦 と 実際の 太陽年 との誤差を埋めるためです。

この導入により、10 月の日付は 11 日繰り上がり、10/4(木) の次は 10/15(金) となっていました。

ncal コマンドでもこのことは考慮されており、-p オプションをつけると、各国の暦がどのタイミングでグレゴリオ暦に切り替わったかを確認することができます。

$ ncal -p
 AL Albania        1912-11-30      IS Iceland        1700-11-16
 AT Austria        1583-10-05      IT Italy          1582-10-04
 ...(省略)...

また、-s で国名コード(上記の -p で表示される 2 つの大文字アルファベット)を指定するとその国のカレンダーを確認することができます。 たとえばイタリア(IT)を指定すると、 1582 年 10 月のカレンダーは以下のようになっており、切り替わっているのを確認できます。

$ ncal -s IT 10 1582
    10月 15821 18 252 19 263 20 274 21 2815 22 2916 23 3017 24 31

日本のグレゴリオ暦の導入

日本では 1872 年(明治 5 年) 12 月 2 日に既存の 天保暦 を廃止し、グレゴリオ暦を導入しました(明治改暦)。

これにより、12 月 2 日の次が 1873 年元旦になりました。

ncal でもこのことは考慮されているはずですが、ncal -p で確認すると以下のように 1918-12-18 と記載されています。

$ ncal -p
 AL Albania        1912-11-30      IS Iceland        1700-11-16
 AT Austria        1583-10-05      IT Italy          1582-10-04
 AU Australia      1752-09-02      JP Japan          1918-12-18
 ...(省略)...

実際に 1872 年 12 月のカレンダーを見ても、日付は飛んでいませんでした。

$ ncal -s JP 12 1872
    12月 18724 11 18 255 12 19 266 13 20 277 14 21 281  8 15 22 292  9 16 23 303 10 17 24 31

逆に 1918 年 12 月のカレンダーを見ると、日付が飛んでいるのが確認できます。

$ ncal -s JP 12 1918
    12月 19183 10 174 11 185 126 137 141  8 152  9 16

何故この日付になっているのか全く理由が分からなかったので、もしこの記事をご覧の方で分かる方が居ましたら、筆者の X まで連絡をいただけますと幸いです 🙇

追記 ①

同じような疑問を持って、深堀りした方のブログ記事を見つけたので参考に掲載します。

https://memo.furyutei.com/entry/20150213/1423824322

所感

最後まで見ていただいてありがとうございました。

相変わらず誰向けの記事かいまいち分かりませんが、少しでも楽しんでいただけたら幸いです。

cal / ncal コマンドの存在自体は前から知っていたのですが、利用するシーンもなかなか無かったので、今回改めて色々調べることで、豊富なオプションがあったり、一部トリッキーな動作があったりと様々な発見があって面白かったです。

今回は FreeBSD 版のみ触ったので、次回は GNU 版も触ってみたり、実際に公開されているコマンドの実装 を解読してみようと思います。