HOWTO · PHP
PHP で文字列を日付と日時に変換する方法
`strtotime()` と `date()` を使った柔軟な日付文字列の解析や、`DateTime::createFromFormat()` と `date_create_from_format()` を使った既知の書式での解析など、PHPで文字列を日付や日時に変換する方法を紹介します。
このページの内容
日付文字列は、PHPが解析するまでは単なるテキストです。解析によって、そのテキストはタイムスタンプまたは日時オブジェクトとして解釈され、フォーマット処理でアプリケーションに必要な形式へ変換されます。一般的で曖昧さのない日付表現には strtotime() を使います。入力が既知のパターンに従う場合は、DateTime::createFromFormat() またはその手続き型の代替である date_create_from_format() を使って書式を明示します。
PHPで日付文字列を解析する方法を選ぶ
柔軟な解釈で問題ない場合は、ISO形式の日付など、一般的な文字列に strtotime() を使います。この関数はUnixタイムスタンプまたは false を返し、date() はタイムスタンプをフォーマットします。固定された入力パターンには DateTime::createFromFormat() を使うと、想定するフィールドの順序を明示でき、日時オブジェクトまたは false が返されます。手続き型の date_create_from_format() 関数でも、静的メソッドを直接呼び出さずに同様の解析ができます。
これらの関数を使っても、曖昧な入力が明確になるわけではありません。ユーザーが異なる日付表記を入力できる場合は、入力時点で期待する書式を定めて検証してください。日時を解釈するときは、タイムゾーンも意図的に選びます。指定しない場合は、PHPに設定されたデフォルトのタイムゾーンが使われます。
strtotime() と date() で柔軟な日付文字列を解析する
一般的な日時文字列は strtotime() で解析し、返されたタイムスタンプを date() に渡します。解析に失敗した値をタイムスタンプとして使わないよう、フォーマットする前に false かどうかを確認してください。この例では入力と出力の書式が固定されているため、マシンの現在時刻に左右されず、結果を再現できます。
次の例を実行します。解析に失敗した場合に表示されるメッセージは、コード内の文字列を保持しているため英語です。
このセクションのコードと表示されるラベルや出力は英語のままです。
<?php
$dateString = '2023-10-15 14:30:00';
$timestamp = strtotime($dateString);
if ($timestamp === false) {
echo "Could not parse the date string.";
} else {
echo date('Y-m-d H:i:s', $timestamp);
}
strtotime() は多くの日付表現を受け付けますが、その柔軟性は入力書式を明確に定めることの代わりにはなりません。結果はタイムゾーン規則に基づいて解釈された時点を表し、date() はPHPのデフォルトのタイムゾーンを使ってタイムスタンプをフォーマットします。元の日時のタイムゾーンが分かっている場合は、サーバー設定に頼らず、その情報を入力に含めるか明示的に適用してください。
DateTime::createFromFormat() で既知の書式を解析する
文字列の構成が決まっている場合は、それに合った書式文字列を指定します。次の書式では、d、m、Y、H、i がそれぞれ日、月、4桁の年、時、分を表します。先頭の ! は、入力に含まれないフィールドを現在の日付の秒などから引き継がずにリセットします。
このセクションのコードと表示されるラベルや出力は英語のままです。
<?php
$dateString = '15-10-2023 14:30';
$dateFormat = '!d-m-Y H:i';
$dateTime = DateTime::createFromFormat($dateFormat, $dateString);
if ($dateTime === false) {
echo "Could not parse the date string.";
} else {
echo $dateTime->format('Y-m-d H:i:s');
}
書式は希望する出力ではなく、入力の構成を表す必要があります。解析後に、希望する出力パターンを指定して format() を呼び出します。結果が false ではなくても、暦の各要素がすべて意図どおりに受け入れられたとは限りません。PHPは範囲外の値を正規化し、警告を報告することがあります。入力を厳密に検証するには、後述のように、解析後に DateTime::getLastErrors() を確認してください。
手続き型の date_create_from_format() 関数を使う
手続き型関数は、PHPの日付関数をすでに使っているコードで便利です。同じ入力書式と文字列を受け取り、解析に成功すると DateTime オブジェクトを、失敗すると false を返します。返された値がオブジェクトであることを確認してから、date_format() でフォーマットしてください。
解析に失敗した場合に表示されるメッセージは、コード内の文字列を保持しているため英語です。
このセクションのコードと表示されるラベルや出力は英語のままです。
<?php
$dateString = '2023/10/15 14:30';
$dateFormat = '!Y/m/d H:i';
$dateTime = date_create_from_format($dateFormat, $dateString);
if ($dateTime === false) {
echo "Could not parse the date string.";
} else {
echo date_format($dateTime, 'Y-m-d H:i:s');
}
これは DateTime::createFromFormat() の手続き型の代替です。どちらも指定した書式に従って解析し、DateTime オブジェクトを生成します。周囲のコードに合うスタイルを選んでください。どちらを使うか決めるためにPHPのバージョンを指定する必要はありません。APIが利用可能か確認する場合は、アプリケーションが対応するPHPバージョンのドキュメントを参照してください。
曖昧な入力、解析エラー、タイムゾーンに対処する
03/04/2023 のような文字列は、日付表記の慣習によって3月4日とも4月3日とも解釈できます。区切り文字だけを見て意図を判断しないでください。入力の構成が分かっている場合は、正確な書式を DateTime::createFromFormat() に渡し、結果を検証します。strtotime() は一般的で明確な文字列を扱うのに便利ですが、ユーザーがどの表記を意図したかまでは推測できません。
DateTime::createFromFormat() と date_create_from_format() は false を返すことがあります。オブジェクトのメソッドや date_format() を呼ぶ前に、その結果を確認してください。また、値を受け入れながら、PHPが日付要素を正規化した場合などに解析警告を報告することもあります。暦上の正確さが重要な場合は、解析診断も確認してください。コード例にあるメッセージは、文字列が変更されていないため英語です。
このセクションのコードと表示されるラベルや出力は英語のままです。
<?php
$dateTime = DateTime::createFromFormat('!Y-m-d', '2023-02-31');
$errors = DateTime::getLastErrors();
if ($dateTime === false || ($errors !== false && ($errors['warning_count'] > 0 || $errors['error_count'] > 0))) {
echo "The date is not valid for the specified format.";
} else {
echo $dateTime->format('Y-m-d');
}
! は指定されていないフィールドをリセットし、getLastErrors() は直近の解析で発生した警告とエラーを報告します。診断の詳細はPHPのバージョンによって異なる場合があるため、アプリケーションが対応する各バージョンで検証方針をテストしてください。特定の地域に属する日時には、その地域の DateTimeZone を作成し、DateTime::createFromFormat() の第3引数(または手続き型関数の対応するタイムゾーン引数)として渡します。入力にUTCオフセットが明示されている場合は、表示用にフォーマットする前に、そのオフセットを保持するか変換するかを意図的に決めてください。