PHPのmktime()で取得したタイムスタンプが8ヶ月前になる事象について
PHPのmktime()関数を使ったカスタマイズで躓いたので情報展開しておきます。動作確認したPHPのバージョンは5.2.13です。
1.問題
次のコードは、指定した日付のエポック秒(1970年1月1日0時0分0秒から、指定した時刻までの通算秒)を取得し、それを年月日時分秒に変換して表示する簡単なサンプルです。
<?php
$date = mktime(01,23,45,08,01,2010);
echo date('Y.m.d A H:i.s',$date);
?>
mktimeの引数は左から順番に、「時・分・秒・月・日・年」となります。このコードを実行すると、
2010.08.01 AM 01:23.45
という結果になるはずですが、実行すると、
2009.12.01 AM 01:23.45
となり、指定したタイムスタンプよりも8ヶ月前になってしまいます。
2.原因と対処
PHPでは、整数に「0」を付与すると8進数として扱われ、「08」は「0」として扱われることが原因です。つまり、指定した値「08月」をmktimeで評価すると「0月」となり、さらに「0月」は前年の12月として評価されるため、1項に記した動作となります。
月の「08」を1桁の「8」に変更することで、この問題は解消します。
<?php
$date = mktime(01,23,45,8,01,2010);
echo date('Y.m.d A H:i.s',$date);
?>
この事象は、月に「08」と「09」を設定した場合に発生します。
3.その他
この事象をみつけた経緯は、Movable Typeのテンプレートタグと組み合わせて、
$entry_date = mktime(<mt:EntryDate format="%H,%M,%S,%m,%d,%Y" />);
ということを行ったためです。この場合、「%m」を「%B」にすることで解消します。
$entry_date = mktime(<mt:EntryDate format="%H,%M,%S,%B,%d,%Y" />);
2010.09.02
をかもとさんからのコメントを受けて、2項を修正しました。
- PHPでvar_dumpの情報をファイルに出力する方法
- PHPで「そのようなファイルやディレクトリはありません」というエラーになる場合の対処
- PHPで「Cannot modify header information - headers already sent by」というエラーになる場合の対処
- PHPで「Parse error: syntax error, unexpected '['」というエラーになる場合の対処
- php.iniファイルのパス・フォルダを探す方法
- PHPで「Fatal error: Maximum execution time of xx seconds exceeded」というエラーになったときの対処
- PHPのpreg_replace()で「The /e modifier is deprecated」となる場合の対処方法
- PHPで改行を削除する方法
- PHPで複数行の文字列を扱う方法
- ファイルアップロード後にPHPでファイルサイズを取得する
この事象は、月に「08」と「09」を設定した場合に発生するようです。
PHPでは、0で始まる文字列は八進数として処理されます。
# 参考:http://css-php.com/php/2-2.htm
八進数で扱えるのは 0 ~ 7 までなので、08(八進数表記) → 0(十進数表記) に変換されるためです。
var_dump(08) 等として確認してみてください。
なので
mktime(01,23,45,08,01,2010)
は、
mktime(1,23,45,0,1,2010)
として評価されてしまい、2010年0月1日→2009年12月1日が返ってくるのです。
>をかもとさん
こんにちは。
情報ありがとうございました。
勉強になりました。
頂いた内容は本文に追記しておきたいと思います。