質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

2904閲覧

PHP の DateTime型, timezoneと unixtime について

Udo

総合スコア9

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2018/08/13 14:02

編集2018/08/13 17:43

前提・実現したいこと

日付文字列とtimezoneを現した数値があります(Asia/Tokyoなら+9、America/Pacificなら-8)。
日付文字列の時刻をUTCとして、timezone の分だけ前後したunixtime を出力したいのですが…
↓(追記、書き直し)
日付文字列とtimezoneを現した数値があります(Asia/Tokyoなら+9、America/Pacificなら-8)。
他から受け取ったunixtimeの値と比較して、片方より未来か過去かを判定しようとしています。
同じ形式で出力してそれを比較すれば良いと思い、
日付文字列とtimezone の値をunixtimeへ変換しようとしたのですが…

発生している問題・エラーメッセージ

私は何かを勘違いしているようです?
(1) は 同じunixtimeが返って、(2)は違うunixtimeが返って…?
なぜ挙動が変わるのかわからず、教えて頂きたいです。

また、(3)で UTCからtzDiff時間前後させた値 == 求めたいunixtime を出力するには、
intval($utcDate->format('U')) + ($tzDiff * 60 * 60) = 求めたいunixtime
としてしまって良いのでしょうか。

該当のソースコード

<?php // (1) $date = new DateTime('now', new DateTimeZone('UTC')); var_dump($date->format('Y-m-d H:s:i').' '.$date->getTimezone()->getName()); var_dump($date->format('U')); var_dump($date->getOffset()); echo("\n"); $date = new DateTime('now', new DateTimeZone('Asia/Tokyo')); var_dump($date->format('Y-m-d H:s:i').' '.$date->getTimezone()->getName()); var_dump($date->format('U')); var_dump($date->getOffset()); echo("\n"); // (2) $utcDate = new DateTime('2018-08-13 00:00:00', new DateTimeZone('UTC')); var_dump($utcDate->format('Y-m-d H:s:i').' '.$utcDate->getTimezone()->getName()); var_dump($utcDate->format('U')); var_dump($utcDate->getOffset()); echo("\n"); $tokyoDate = new DateTime('2018-08-13 00:00:00', new DateTimeZone('Asia/Tokyo')); var_dump($tokyoDate->format('Y-m-d H:s:i').' '.$tokyoDate->getTimezone()->getName()); var_dump($tokyoDate->format('U')); var_dump($tokyoDate->getOffset()); echo("\n"); // (3) $tzDiff = 9; // $tzDiff = -8; if (0 <= $tzDiff) { $utcDate->modify('+'.$tzDiff.' hours'); } else { $utcDate->modify('-'.abs($tzDiff).' hours'); } var_dump($utcDate->format('Y-m-d H:s:i').' '.$utcDate->getTimezone()->getName()); var_dump($utcDate->format('U')); # UTCから9時間進めた値 == 東京のunixtime が返ると思ったのに… var_dump($utcDate->getOffset()); echo("\n");

試したこと

http://codepad.org/VDaCKgL3

補足情報(FW/ツールのバージョンなど)

// output
string(23) "2018-08-13 14:37:01 UTC"
string(10) "1534168897"
int(0)

string(30) "2018-08-13 23:37:01 Asia/Tokyo"
string(10) "1534168897"
int(32400)

string(23) "2018-08-13 00:00:00 UTC"
string(10) "1534118400"
int(0)

string(30) "2018-08-13 00:00:00 Asia/Tokyo"
string(10) "1534086000"
int(32400)

string(23) "2018-08-13 09:00:00 UTC"
string(10) "1534150800"
int(0)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

(1) は 同じunixtimeが返って、(2)は違うunixtimeが返って…?
なぜ挙動が変わるのかわからず、教えて頂きたいです。

  1. unixtimeは「UTCの」1970年1月1日0時0分0秒からの経過秒数のことです。

そのため、どんなタイムゾーンであってもnowを指定すれば常に同じunixtimeが取得されます。
イメージとしては、ロンドンと日本で電話で話しながら「現時点でのUTC1970年1月1日0時0分0秒からの経過秒数」をお互い言いあうようなものです。(国際電話の遅延は無視するとして)同じ秒数を言い合うことになるはずです。

  1. (2)では、それぞれのタイムゾーンの2018-08-13 00:00:00からunixtimeを逆算しています。

これは、日本とロンドンでそれぞれ「日付が変わった瞬間のUTC1970年1月1日0時0分0秒からの経過秒数」をそれぞれ言い合っているようなものなので、日本の方が日付が変わる瞬間は早く到達します。

また、(3)で UTCからtzDiff時間前後させた値 == 求めたいunixtime を出力するには、
intval($utcDate->format('U')) + ($tzDiff * 60 * 60) = 求めたいunixtime

tzDiffがサマータイム等を考慮しない純粋な時間の差という事であればその通りです。
ただ、質問冒頭の

日付文字列の時刻をUTCとして、timezone の分だけ前後したunixtime を出力したいのですが…

というのがuniximeの定義への誤解に基づく仕様な気がするので、最終的にどういうことをしたいのかを追記されると良いと思います。


追記に対する回答

日付文字列とtimezoneを現した数値があります(Asia/Tokyoなら+9、America/Pacificなら-8)。
他から受け取ったunixtimeの値と比較して、片方より未来か過去かを判定しようとしています。
同じ形式で出力してそれを比較すれば良いと思い、
日付文字列とtimezone の値をunixtimeへ変換しようとしたのですが…

この発想は正しいので、(2)の方法でそれぞれDateTimeオブジェクトを作ってunixtimeで比較するか、
オブジェクトをそのまま比較(こんなことできるんですね)すればどちらが未来かわかりますね。

(2)の場合、
string(23) "2018-08-13 00:00:00 UTC"
string(10) "1534118400"

string(30) "2018-08-13 00:00:00 Asia/Tokyo"
string(10) "1534086000"
だと、UTCの方が値が大きい(1970/1/1からの経過秒数が多い)ので同じ時間でUTCとJSTだとUTCの方が未来(日本よりロンドンの方が日付変更が遅い)である
と判定できます。

投稿2018/08/13 14:49

編集2018/08/13 19:05
tanat

総合スコア18713

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Udo

2018/08/13 17:51

> というのがuniximeの定義への誤解に基づく仕様な気がするので、最終的にどういうことをしたいのかを追記されると良いと思います。 ありがとうございます。まだどうすべきかはっきり理解できず、 したいことと考えたことを追記してみました。
Udo

2018/08/14 12:07

>この発想は正しいので (3)は廃止して↓こんな感じでdateTimeを作って、そこから比較することにしようと思います。 $date = new DateTime('2018-08-13 00:00:00'.sprintf("%+03d", $tzDiff).'00'); 回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問