はちど

ボードゲームのレビューなど。

*

カレンダーを作ってみた。

      2013/10/29

Hachiです。
最近買ったものシリーズ今回はこちらですどーん。

MOLESKINE LEGOコラボ プレーンノートブックです。
モレスキンはちょっと…とか言っておきながら、半額だったのでついつい購入してしまいました。
ロディアラマより一回り大きいA5サイズ。そしてプレーン(無地)。
それらを活かして、頭の中にあるものをとにかく書き出して整理するための考察ノートにしようかなと思います。
Think with your hands.(手を動かして考えよう)というMOLESKINEとLEGOの共通の哲学に則って。

んでレビューですが。
紙質はまあ薄っぺらい紙の手帳並みで、噂通り万年筆のインクは染みて裏抜けしますね。
水性ボールペンでもインクの出が良いものは簡単に抜けそうで怖いくらいです。
2.0mmシャープペンシルでわしわし書こうにも、紙の薄さのせいか既に書いたページの汚れがひどい。
というわけで、最近活躍の場がめっきり減った油性ボールペンが日の目を浴びています。
# それも筆圧かかりすぎてページがボコボコになっちゃうのがあれですが。
# 紙質って大事だなー、日本のノートは安いのに良い紙使ってるんだなー、と思います。

多分、これ使い切ったら次はRHODIA WebNotebookのA5版を買います。

閑話休題。
最近のお仕事で、スケジュール管理系のWebシステム構築をやってます。
ちょっと大きめの案件でCMSの利用も考慮したのですが、CMSを利用しての開発にまだ不慣れというこちらの事情もあり、やっぱり自分で作ろうということに。

さて、スケジュール管理システムで最も重要なパラメータは日付と時間です。
そしてそれらが最もわかりやすく表現できるインターフェースは、カレンダー形式以外にはありません。
見慣れているインターフェースこそ多くの人にとって最も使いやすく、Web上のシステムでもアナログなモノの模倣は良いUIへの近道だと思っています。

当たり前に使われるインターフェースは、大抵は当たり前に使えるようになっています。
CMSを使えば当然付随して使えるようになるものですし、そうでなくてもプラグインなんか調べれば山ほどあるでしょう。
でも、カレンダーですよ。そのくらい自分で作れるんじゃないの
というわけで自分で作ってみました。


マンスリーカレンダー描画アルゴリズム考察メモ。
以下はここに書いてあることを文章にてつらつら説明していきます。

まずは、描画する月の1日が何曜日か?を確定させます。
マンスリーカレンダーの1行目の何番目からカウントアップをスタートさせるか、という話です。
2013年1月1日(火)を基準に、と書いてますが、日曜始まりのカレンダーにする都合上2012年12月30日(日)を基準にしています。
そこから数えて描画月1日は何日目にあたるのかを計算し、それを7で割った余りで曜日を確定させています。

西向く士(さむらい)小の月」ということで、2月は28日、4,6,9,11月は30日までしかありません。
それ以外の1,3,5,7,8,10,12月は31日まであります。そして、1年間は365日です。
また、次の閏年は2016年なので、(2012+4n)年2月の日数は1ずつ増えます。

以上からY年M月1日の曜日はこんな感じで計算できます。
[(Y-2013)*365+{(Y-2013)\4}+MonthSum(M-1)+2}Mod7
# MonthSum(M)は1月からM月までの日数の合計。

これでY年M月のカレンダーはとりあえず描画できるのですが、1日より左や最終日より右には前月/次月の日付を埋めたい。
描画の際は週(5行)×日(7列)の二重ループが発生するので、それを利用してさらにもう一手間。

1週目(1行目)描画の際は、列のループ用変数と先ほどの曜日計算で得た結果を比較して
曜日計算の数字より列ループ変数の数字が小さければ前月なので、前月の数字を埋めていきます。
また、5週目の描画では当月の日数をカウントする変数と最終日の数字を比較して次月の数字埋めを同様に実施。

さらにさらに、時折カレンダーは4行で済んでしまうことも稀にあるので、その処理もついでに。
日曜始まりのカレンダーでは、1日が日曜日かつ1ヶ月が28日の場合、5行目が全く不要になります。
この処理は割と簡単で、5周目描画の際の次月数字埋め分岐に入った際にそれが日曜日であるかどうかという分岐をもうひとつ作って
trueであれば5行目の描画自体を全てスキップするという処理にすればいいだけです。
# ちなみに2年後の2015年2月がこの「カレンダーが4行で済んでしまう稀な一ヶ月」です。

ここまでで、カレンダー描画アルゴリズムが完成です。
中身としては基本の基本、プログラミング基礎とかアルゴリズム基礎なんかでよく作るプログラムかなと思います。
でも改めて作ってみようと思うと結構躓くところがあったりもして、いい勉強になりました。

また、既存のものを使うよりも簡単に応用が利くというところは、実際に使うものを作る上では重要なポイントだと思います。
そんなに時間もかからなかったですし、やってよかったなーと思ってます。
よく考えればDateDiff関数とかそのへん使えば前半の計算式不要なんですがw
そこも含めて、たまにはこういう細かい計算とかに触れて頭をほぐすのもいいなぁと感じました。

2013/03/05 追記。
上記アルゴリズムに足りてないところがありました。
「カレンダーが6行必要になる月」…。
4行で済む月より頻繁にあって、今月(2013年3月)もそうなのに、すっかり抜けてました。

アルゴリズム的には、5行目の土曜日の処理が終わった段階でその月の残り日数があれば6行目の記述をする処理を行う感じで。
あるいはいっそ各行の土曜日の後にその処理を入れてしまえば、4行で済む場合も6行必要な場合もひとつの条件で済みますね。
コードの最適化と一般化を考えれば、その方が良いのかも知れません。
# カレンダー描画の一般化…ひと月が何日であっても破綻なく描画できるってことですね。なんだろうそれ。

sns-widget

更新情報の確認にはこちら!

 - Web技術, 文房具 ,