- 2008年8 月20日(水)
- PHP
shimazakiです。
今日は前に社内で遊んだ課題の中から、「指定日が何週目なのかを取得するコード」のお話をしたいと思います。
何週目かを取得するコード(日曜日固定)
要件としては以下になります。
- 日曜日を週の始まりとする
- 一日から最初の土曜日までを「1週目」とする
真面目に考えると指定日の日付と、一日の曜日と指定日の曜日との差分とをどうこうすれば出てくると思いますが、ちょっと手を抜くことにします。
上記要件を踏まえた上でカレンダーを見てみると、土曜日の日付がその週で最大の日付になっていることが分かると思います。
なので、指定日の日付の週の土曜日の日付が分かれば計算が単純になります。
幸いPHPのdate関数を使用すれば日〜土が0〜6で取得出来ますのでちょうど良いですね。
function getWeek( $timestamp ){
return ceil( ( date(’d',$timestamp) + ( 6 - date(’w',$timestamp) ) ) / 7 );
}
指定日から土曜日までの差分を指定日に加算し、一週間の日数分の7で割り、切り上げれば何週目かが取得できます。
関数なのでワンライナーにする必要はないのですが(そもそもワンライナーって言っていいのかこれ)、つい。
何週目かを取得するコード(基準曜日変動)
世のカレンダーはだいたい日曜日始まりですが、もしかしたら月曜日始まりのシステムを作成することもあるかもしれません。
そこで、基準日も変更できるように改良します。
要件としては以下になります。
- 週の始まりを指定できるようにする
- 一日から上記週の始まりの前日までを「1週目」とする
先程はその週の最大の日付である土曜日がPHPのdate関数の戻り値と一致したために楽でしたが、土曜日以外ではそうはいきません。例えば水曜日基準の場合、日月火曜日は同じ考えが通用しますが、木金土曜日は差分を取ろうとするとマイナスになってしまうため、期待通りになりません。
なので、基準日の前後で変更を加えてみます。
function getWeek($timestamp,$start){
$w = date(’w',$timestamp);
if($start == 0){
$plus = 6-$w;
}else{
$last_w = $start-1;//基準日の前ならばそのまま差分を取り、後ならば次の週から差分を取る
if($last_w >= $w){
$plus = $last_w - $w;
}else{
$plus = ($last_w+7) - $w;
}
}
return ceil( ( date(’d',$timestamp) + $plus )/7 );
}
どうでしょう。悪くないかもしれませんが、不細工になってしまった感が否めません。
もう一度考え直してみることにします。
- 指定日よりも前の曜日なら問題なく計算できる
- 指定日よりも後の曜日なら同じように計算すると前の週になってしまうため、7を加算して計算する
- 加算する値は0-6の間であることは確定
指定日よりも前の曜日に7を加算すると当然0-6の範囲を超えてしまうのでNGなのですが、とりあえず足して7より大きい場合は7を減算すれば期待通りの動作になりそうです。
ただし、「7より大きければ7を減算する」という処理はifを伴ってしまうため、元々のコードと処理内容はあんまり変わりません。また、「7を加算して7より大きければ7を減算する」というのは凄い無駄なことをしているような気もします。
そこで手っ取り早く0-6の範囲内に収まるように7進数に変換してみます。これで7を超えない分は問題なく、7を超える分も桁の繰り上がりが起こり、期待する値が取得しやすくなりました。
function getWeek($timestamp,$start){
return ceil( ( date(’d',$timestamp) + substr(base_convert(((($start-1)+7)-date(’w',$timestamp)),10,7),-1) )/7 );
}
$startより大きいかどうかは無視して、とりあえず足して引いて、7進数にして、1桁目を取得すれば週末までの差分がとれるので、あとは日曜日のパターンと同じです。
それにしても普段使わない関数ってちょっとドキドキしますね。7進数って単語も今回初めて使いました。
- Newer: PHPer向けJavaScript入門
- Older: MondoRescueによるバックアップとリカバリ(CentOS5.1)

