👌

PHPで日時(ISO8601)の文字列をDateTimeに変換する

2021/09/23に公開

PHPで日時(ISO8601)の文字列をDateTimeに変換したい

SalesforceのAPIから返ってくるDateTimeをPHPでパースしようとして詰まったのがこのケースです。Salesforceの画面上は日本時間で見えている場合でもUTCで返ってきていました。しかもマイクロ秒付きで。

Let's try

ISO8601にDateTime::ISO8601は使えない

まずは失敗例からです。以下のようにDateTime::createFromFormatでDateTime::ISO8601を指定するとbool(false)になります。残念。

<?php

$str = "2019-06-10T09:00:00.000+000";
$datetime = DateTime::createFromFormat(DateTime::ISO8601,$str);
var_dump($datetime);
// bool(false)

ドキュメントを見てみると記載があるのですがDateTime::ISO8601は使えないんですね。うーん。

注意: この書式は ISO-8601 との互換性がありませんが、敢えてそのまま残しています。 下位互換性を保つためです。ISO-8601 互換の書式を使いたい場合は、 DateTime::ATOM あるいは DATE_ATOM を使いましょう。

https://www.php.net/manual/ja/class.datetime.php

書式を自分であわせるしかなさそう

ATOMを使いましょうと書いてあるものの今回はマイクロ秒まであるせいか結果は変わらず失敗でした。なので、パースできる書式をあてるしかないようですね。以下のドキュメントのフォーマット文字を参照すると..。ポイントは+で秒以降を切り捨ててることくらいでしょうか。
https://www.php.net/manual/ja/datetime.createfromformat.php

<?php

$str = "2019-06-10T09:00:00.000+000";
$datetime = DateTime::createFromFormat('Y-m-d\TH:i:s+',$str);
print_r($datetime);
// DateTime Object
// (
//     [date] => 2019-06-10 09:00:00.000000
//     [timezone_type] => 3
//     [timezone] => UTC
// )

無事、DateTimeになりましたね!ホッ

これだとまだUTCのままなので、日本にタイムゾーン変えればOK。
DateTime::createFromFormatで第3引数にタイムゾーンを渡せますが、そこにAsia/Tokyoをわたしてしまうと、この例でいうと9時が日本時間になるので、UTCでDateTime::createFromFormatしたあとにタイムゾーンをセットすればうまくいきます。

<?php

$str = "2019-06-10T09:00:00.000+000";
$datetime = DateTime::createFromFormat('Y-m-d\TH:i:s+',$str);
$datetime->setTimezone(new DateTimeZone('Asia/Tokyo'));
print_r($datetime);
// DateTime Object
// (
//     [date] => 2019-06-10 18:00:00.000000
//     [timezone_type] => 3
//     [timezone] => Asia/Tokyo
// )

Discussion