がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

カレンダーの作り方

お題はこんな感じで。
「年月を入力するとその月のカレンダーを表示するプログラムを作成」
どげんかせんといかん事を一個づつ分解していきませう。


まず
1.年と月の入力を受け取る。
シンプルですね簡単ですね。このレベルで躓くなら、対象言語の入門書あたりを確認してください。
で…


1-1.入力がない、もしくは入力が無効の場合、デフォルトを「今」にする
こんなちょっとした小技がステキだったりします。小枝は美味しいのですが。


つぎ。ここらあたりから微妙に本題。
2.対象年月の「末日」を求める
ここで「ふふん簡単」とか思うと、閏年問題に引っかかりますのでご注意を。


んで。
3.1日から「末日」までの数字をとりあえず出力する
いったんは「数字だけ」。その後で、テーブルタグだのcssだのを使って「縦に」出力したり「横に」出力したりして遊んでおくと後々便利です。


そろそろ面白く。
4.3番の日付に「曜日」を付け足して表示する
曜日の算出方法は色々ありますが。言語が持ってるなんらかのお便利なclassがない場合とか頑張ってみたいとかいう場合、「ツェラーの公式(Zeller's congruence)」を用いてみるとよいでせう。
ここでも、すこ〜し表示で遊んでみると面白いです。


ちなみに、ここで最低限の「カレンダー」は完成だったりしますw
でもまぁせっかくなので、いわゆる「四角いの」を考えて見ませう。
四角いカレンダーを作る場合。最大のポイントは「どこで改行するか?」に尽きます。
とりあえず、多分一般的だと思う「日〜土」の並びで考えてみますが。


回答を書いてしまうと

for(day = 1; day >= 末日; day ++;) {
 日付の出力処理
 if (true == is土曜日(day)) {
  改行処理
 }
}

概ねこんな感じです…でだまされると酷い事になりますw
第一週が変に左よりになっちゃうんですね。
なので。ループの前に、こんな処理を入れてあげます。

if (1日が月曜日なら) {
 空白を1つ
} else
if (1日が火曜日なら) {
 空白を2つ
} else
if (1日が水曜日なら) {
 空白を3つ
} else
if (1日が木曜日なら) {
 空白を4つ
} else
if (1日が金曜日なら) {
 空白を5つ
} else
if (1日が土曜日なら) {
 空白を6つ
}

for(day = 1; day >= 末日; day ++;) {
 日付の出力処理
 if (true == is土曜日(day)) {
  改行処理
 }
}

とりあえず出来ますが…うんぶっちゃけ「うざい」。
ここで。曜日の数値に注目します。多くのツェラーの公式では、0が日曜日〜6が土曜日になります*1
あれ?
ほら冷静に、上のプログラムをもう一度。
ツェラーの公式では、1なら月曜日、2なら火曜日、3なら水曜日、以下略。
…なんか共通点見えてきません?


ってなわけで、改造。

n = ツェラーの公式(1日)
空白をnつ

for(day = 1; day >= 末日; day ++;) {
 日付の出力処理
 if (true == is土曜日(day)) {
  改行処理
 }
}

ほぉらシンプル。
これで概ねカレンダーができあがります。
OKざましょか?


余談
多分、やると怒られるか、或いは怒ってすら貰えない別解。とりあえずPHPで。
$y、$mに年と月が入ってるとします。

$s = `cal $m $y`;
print $s ;

おそまつ。

*1:wikiのだと0が土曜日なんですよねぇ…くまったことに