メニューを閉じる

テクノデジタルグループ

メニューを開く

2019.06.25

プログラミング

MySQLから取得したDATE型をPHPで文字列に変換したら紀元前2年11月30日が表示された話

こんにちは。ZYです。

MySQL上から取得した値をJSONやCSVなどに文字列で出力したい、という時はあると思います。
その際に以下のようなPHPを書いてみると、

$dateTimeObj = new \DateTime($value);
$dateStr = $dateTimeObj->format('Y-m-d');

var_dump($dateStr);

こんな出力に。

-0001-11-30

西暦マイナス1年、紀元前2年の11月30日が出力されます。古代ローマ帝国初代皇帝アウグストゥスが活躍した時代です。
なんだこりゃ。と戸惑うのですが、これはMySQLでいうとDATE型のカラムに「0000-00-00 00:00:00」が入っていた場合に、それをそのまま文字列としてDateTimeを初期化。再度フォーマットしたい際に、PHPが表示する日付。

PHPのdate formatには以下のような仕様があります。出典:公式PHP マニュアル

シンボル dd と DD について、 オーバーフローやアンダーフローすることができます。 つまり、 0 日は先月の最終日の意味になりますし、 オーバーフローすると翌月に繰り越しになります。 このルールにより、”2008-08-00″ は “2008-07-31” と同一になり、 “2008-06-31” は “2008-07-01” と同一になります ( 6 月は 30 日までしかないので)。

では、”0000-00-00″の場合はどうなるかということも実例で書いています。

文字列 “0000-00-00” についても同様に “-0001-11-30” へと変形されます。 (ISO 8601 における -1 年は、予測的グレゴリオ暦 (proleptic Gregorian calendar) で言うところの紀元前 2 年になります。)

「〇月〇日の~日前」みたいな計算をする際に存在しない日付を指定しても、計算してくれる親切仕様が紀元前まで適応されたわけです。

ちなみに、この現象に対する正しい対処法は、「そもそもMySQLのDATE型に”0000-00-00 00:00:00″を入れない」です。
ついでにいえば、MySQL5.7以降であれば、デフォルトNO_ZERO_DATE, NO_ZERO_IN_DATEモードがONになっているため、”0000-00-00 00:00:00″を入れることが出来ないようになっているので、こんな現象も起こらない気がします。


【記事への感想募集中!】

記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!
  • こんな記事が読んでみたい、こんなことが知りたい、調べてほしい!という意見も募集中!
  • いただいた感想は今後の記事に活かしたいと思います!

感想フォームはこちら


【テクノデジタルではエンジニア/デザイナーを積極採用中です!】

下記項目に1つでも当てはまる方は是非、詳細ページへ!
  • 自分でアプリを作ってみたい
  • ITで世の中にワクワクを生み出したい
  • 使いやすさ、デザインにこだわったWebサイトを開発したい

採用情報の詳細はこちら


Qangaroo(カンガルー)

  • 徹底した見やすさと優れた操作性で、テストの「見える化」を実現。
  • テストの進捗が見える。開発がスマートに進む。
  • クラウド型テスト管理ツール『Qangaroo(カンガルー)』

【テクノデジタルのインフラサービス】

当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。

https://www.tcdigital.jp/infrastructure/

最近の記事