先日、直前1週間以内で特定の曜日の日付を取得する必要があったので、その時書いた処理を拡張し最近1週間以内で指定された曜日が何月何日かを取得する関数を書いてみました。
日付の求め方
直前1週間以内で特定の曜日の日付を求める場合、 Datetime オブジェクトにある DateTime::format('w') を利用して、以下のように求めることができます(参考)。
特定の曜日が日曜日の場合
日曜日の場合どの日から計算しても今週の日付になることから、今日の日付から日曜日の日付までの差を求めることで計算できます。
- 今日が日曜日から何日たっているか求める
- 今日の日付から 1. で求めた日数分引く
<?php
function get_last_date_from_dow($dow = 0){
$today = new Datetime();
$days_from_dow = $today->format('w') - $dow;
return $today->sub(new DateInterval('P'.$days_from_dow.'D'));
}
特定の曜日がその他の曜日の場合
その他の曜日の場合、場合によっては求める日付が先週になることがあります。
その場合、先ほどの求め方だと -n日 の差が出てしまうため、先ほどの 2. で日数を足すことになっていまいます。そのため、先週の日数を考慮した上で日付を求める場合少し工夫が必要になります。
曜日の特性に着目すると、以下のことが言えます。
- 7日周期
- 各曜日は同じ順番で出てくる
これらを踏まえると、先週の日付を求める場合、以下に示すように週の終わりから特定の曜日が何日経っているかを求め、今日が日曜日から何日たっているか求めれば、うまくいきそうです。
- 特定の曜日が週の終わりから何日たっているか求める
- 今日が日曜日から何日たっているか求める
- 今日の日付から 2. で求めた日数分引く
<?php
function get_last_date_from_dow($dow){
$today = new Datetime();
$days_from_dow = 7 - $dow + $today->format('w');
return $today->sub(new DateInterval('P'.$days_from_dow.'D'));
}
しかし、この求め方では問題が生じてしまいます。先週の日付を求めようとするときの問題を解消するために、上記の求め方を出しましたが、今度は求める日付が今週の日付であった場合に先週の日付が求まってしまう、すなわち7日分余計に引いてしまうという問題が生じていまいます。
改めて、曜日の特性に着目して考えると、先ほど求めた日数から7の剰余を取れば、7日分余計に引いてしまう部分は解消できそうです。
最終的な求め方は以下になります
- 特定の曜日が週の終わりから何日たっているか求める
- 今日が日曜日から何日たっているか求める
- 1. と 2. の和から7の剰余を求める
- 今日の日付から 3. で求めた日数分引く
デモ
ソースコード
<?php
/**
* 指定された曜日が最近1週間以内だと何月何日かを取得する
* 曜日の数字が0〜6の整数でない時falseを返す
* @param int $dow 曜日(day of week)の整数(0〜6)
* @return Datetime|bool
**/
function get_last_date_from_dow($dow){
try {
if(is_int($dow) && $dow >= 0 && $dow < 7){
$today = new Datetime();
$days_from_dow = (7 - $dow + $today->format('w')) % 7;
return $today->sub(new DateInterval('P'.$days_from_dow.'D'));
} else{
throw new Exception('引数には0〜6の整数のみ使用できます');
}
} catch (Exception $e) {
echo '例外: '.$e->getMessage().PHP_EOL;
return false;
}
}