0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

strtotime関数の罠

Last updated at Posted at 2023-03-05

strtotime関数はどんな引数でも頑張って変換しようとする

[strtotime — 英文形式の日付を Unix タイムスタンプに変換する]
https://www.php.net/manual/ja/function.strtotime.php

注文データをCSVファイルで読み込んで、データベースに取り込むといった処理の流れで、注文日時が全く違う日時で取り込まれているといった不具合が報告された。
内容を確認すると以下のプログラムに不具合があることがわかった。


// $input_order_date_time = CSVから取り込んだ日時
$order_date_time = date('Y-m-d H:i:s', strtotime($input_order_date_time));

strtotime関数はPHPらしい関数でどんな引数が指定されようと頑張って何とか変換しようとする、とてもありがた迷惑な関数である。
せめて変換に失敗したらfalseを返してほしい・・・

以下にstrtotime関数がどんな値を吐き出すかテストをしてみた。

// 今日は2023-03-05です
$input_order_date_time = date('Y-m-d H:i:s');
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 14:54:24

$input_order_date_time = '2023-03-05 11:15:00';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 11:15:00

$input_order_date_time = '2023/03/05 11:15:00';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 11:15:00

$input_order_date_time = '20230305 111500';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 11:15:00

$input_order_date_time = '20230305';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 00:00:00

$input_order_date_time = '2023-03';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-01 00:00:00

$input_order_date_time = '202303';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 20:23:03

$input_order_date_time = '11:15:00';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 11:15:00

$input_order_date_time = '111500';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 11:15:00

$input_order_date_time = 'あああああ';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 1970-01-01 00:00:00

おわかりいただけただろうか・・・

ありがた迷惑な変換を一個ずつ見てみる

$input_order_date_time = '2023-03';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-01 00:00:00

勝手に3/1になっています。
3月は31日まであるのでどの日付を指定していいかわからずfalseが返ってきてほしいところ

$input_order_date_time = '202303';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 20:23:03

こちらは勝手に今日の日付の20:23:03に変換されています。
この引数は時間であると勝手に解釈されて、なおかつ自動で今日日付で変換されています。

$input_order_date_time = '111500';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 2023-03-05 11:15:00

時間であると解釈されました。はい。

$input_order_date_time = 'あああああ';
echo date('Y-m-d H:i:s', strtotime($input_order_date_time));
// 1970-01-01 00:00:00

プログラマーなら誰でも知っている例の日付に変換されました。
頼む、falseを返してくれ。

以上です。

strtotime関数に値を渡す際は事前にかなり入念なチェックを入れる、またはフォーマットをがっちり固めておくといった事が必要ですね。

今回はフォーマットを定めておらず、自由に値を設定でき、柔軟に日付変換をするといった処理となっていたため不具合を起こしていたようです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?