MySQLとPHPで曜日の数値表現が非常に紛らわしい件

MySQLPHPで曜日の数値表現を使った処理を行ったら非常に紛らわしかったのでメモ。

MySQLの曜日関数

MySQLには日付から曜日の数値表現を求める関数が2つある。 DAYOFWEEK関数と、WEEKDAY関数である。 この2つの関数が単にエイリアスであればいいのだが、 それぞれ違う結果を返す。

DAYOFWEEK関数

まずは、DAYOFWEEK関数の結果を見てみる。

SELECT
    DAYOFWEEK('2012-12-02')
  , DAYOFWEEK('2012-12-03')
  , DAYOFWEEK('2012-12-04')
  , DAYOFWEEK('2012-12-05')
  , DAYOFWEEK('2012-12-06')
  , DAYOFWEEK('2012-12-07')
  , DAYOFWEEK('2012-12-08')
\G

上記のSQL実行すると、結果は以下のようになる。

*************************** 1. row ***************************
DAYOFWEEK('2012-12-02'): 1
DAYOFWEEK('2012-12-03'): 2
DAYOFWEEK('2012-12-04'): 3
DAYOFWEEK('2012-12-05'): 4
DAYOFWEEK('2012-12-06'): 5
DAYOFWEEK('2012-12-07'): 6
DAYOFWEEK('2012-12-08'): 7
1 row in set (0.00 sec)

2012-12-02が日曜日なので、日曜日スタートで1から始まり、土曜日が7で終了、という形式である。

WEEKDAY関数

次に、WEEKDAY関数の結果を見てみる。

SELECT
    WEEKDAY('2012-12-02')
  , WEEKDAY('2012-12-03')
  , WEEKDAY('2012-12-04')
  , WEEKDAY('2012-12-05')
  , WEEKDAY('2012-12-06')
  , WEEKDAY('2012-12-07')
  , WEEKDAY('2012-12-08')
\G

こちらを実行すると、次のような結果を得られる。

*************************** 1. row ***************************
WEEKDAY('2012-12-02'): 6
WEEKDAY('2012-12-03'): 0
WEEKDAY('2012-12-04'): 1
WEEKDAY('2012-12-05'): 2
WEEKDAY('2012-12-06'): 3
WEEKDAY('2012-12-07'): 4
WEEKDAY('2012-12-08'): 5
1 row in set (0.00 sec)

WEEKDAY関数では、月曜日スタートで0から始まり、日曜日が6で終了、という形式である。

PHPの曜日の数値表現

PHPの曜日の数値表現もフォーマット文字列'w'と'N'の2種類で得られる結果が存在する。

まずはwの結果。

<?php
for($i = 2; $i <= 8; ++$i) {
  $d = new DateTime();
  $d->setDate(2012, 12, $i);
  echo $d->format('Y-m-d'),': ',$d->format('w'),"\n";
}

上記の結果は以下のようになる。

2012-12-02: 0
2012-12-03: 1
2012-12-04: 2
2012-12-05: 3
2012-12-06: 4
2012-12-07: 5
2012-12-08: 6

次にNの結果。

<?php
for($i = 2; $i <= 8; ++$i) {
  $d = new DateTime();
  $d->setDate(2012, 12, $i);
  echo $d->format('Y-m-d'),': ',$d->format('N'),"\n";
}

上記の結果は以下のようになる。

2012-12-02: 7
2012-12-03: 1
2012-12-04: 2
2012-12-05: 3
2012-12-06: 4
2012-12-07: 5
2012-12-08: 6

MySQLと同じ形式が無い。 ということで、DAYOFWEEK関数と'w'もしくはWEEKDAY関数と'N'の組み合わせで1補正する、というように気をつける必要がある。

もしくはMySQLはDATE_FORMAT関数で%Wを指定、PHPではフォーマット文字'l'を指定してやれば'Sunday'のような文字列で一致するのでこれで扱ってやるのがいいのかもしれない…。

参考