私はこの状況に、1年ちょっと前にプライベートジェットオペレーターのために書いたPHP/MySQLアプリケーションで広範囲に対処しました。これら2つのプラットフォームでタイムゾーンを処理するためのさまざまな戦略がありますが、私がそれをどのように行ったかを説明します。MySQLサーバーをUTCに設定し、ユーザープロファイルのサインアッププロセス中にユーザーが指定したタイムゾーンで各PHPスクリプトを実行します。
MySQLとPHP(PHP 5.2以降)はどちらもネイティブの日時データ型を持っています。MySQLのdatetimeはプリミティブデータ型ですが、PHP5.2以降では組み込みのDateTimeクラスが提供されています。MySQLの日時データ型にはタイムゾーンのメタデータは含まれていませんが、PHPのDateTimeオブジェクトには常にタイムゾーンが含まれています。PHP日時コンストラクターが2番目の引数でオプションのタイムゾーンを指定しない場合、PHP日時コンストラクターはphp環境変数を使用します。
MySQLとPHPの両方で、構成ファイルにデフォルトのタイムゾーンが設定されています。MySQLは、コマンドで接続が開始された後にユーザーが別のタイムゾーンを指定しない限り、各db接続の構成ファイルに設定された日時SET time_zone = [timezone];
を使用します。PHPは、サーバー構成ファイルで設定されたタイムゾーンを使用して各スクリプトのタイムゾーン環境変数も設定します。この環境変数はdate_default_timezone_set()
、スクリプトの開始後にPHP関数を使用してオーバーライドできます。
PHP DateTimeクラスには、 PHPDateTimeZoneオブジェクトであるtimezoneというプロパティがあります。DateTimeZoneオブジェクトは、正確なタイムゾーンの文字列を使用して指定されます。タイムゾーンのリストは包括的であり、世界中に数百の個別のタイムゾーンがあります。 PHPのタイムゾーンは、夏時間を自動的に考慮します。
ユーザーがWebアプリで日時を生成するときに、ユーザーのプロファイルのタイムゾーンでPHP日時オブジェクトを作成します。次に、このsetTimezone
メソッドを使用して、DateTimeオブジェクトをUTCタイムゾーンに変更します。これで、UTCでのユーザーの日時がわかり、値をデータベースに保存できます。DateTimeformat
メソッドを使用して、MySQLで受け入れられる形式の文字列としてデータを表現します。
したがって、ユーザーは日時を生成し、ユーザーが指定したタイムゾーンでPHP日時オブジェクトを作成します。
// set using an include file for user profile
$user_timezone = new DateTimeZone('America/New_York');
// 1st arg in format accepted by PHP strtotime
$date_object1 = new DateTime('8/9/2012 5:19 PM', $user_timezone);
$date_object1->setTimezone(new DateTimeZone('UTC'));
$formated_string = $date_object1->format('Y-m-d H:i:s');
$query_string = "INSERT INTO `t_table1` (`datetime1`) VALUES('$formated_string')";
データベースから値を取得するときは、UTCで作成してから、ユーザーのタイムゾーンに変換します。
$query_string = "SELECT `datetime1` FROM `t_table1`";
$date_object1 = new DateTime($datetime_string_from_mysql, new DateTimeZone('UTC'));
$date_object1->setTimezone($user_timezone);
$string_for_display_in_application = $date_object1->format('m/d/Y g:i a');
この方法を使用すると、日時の値は常にデータベース内のUTCに保存され、ユーザーは常に自分のプロファイルのタイムゾーンの値を経験します。PHPは、必要に応じて各タイムゾーンの夏時間を修正します。
1つの落とし穴:この説明は、MySQLタイムスタンプデータ型をカバーしていません。タイムスタンプデータ型ではなく、MySQL日時日付型を使用して日時値を格納することをお勧めします。タイムスタンプのデータ型については、こちらのマニュアルで説明されています。
編集: DateTimeZoneクラスの静的メソッドであるlistIdentifiers
を使用して、すべてのPHPタイムゾーン文字列を含む配列を作成できます。