home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

PHP/HTTP DateとGMTの処理について実験メモ1

PHP/HTTP DateとGMTの処理について実験メモ1

PHP / HTTP DateとGMTの処理について実験メモ1
id: 266 所有者: msakamoto-sf    作成日: 2007-05-03 22:57:28
カテゴリ: PHP 

きっかけは画像を出力するPHPを作ってたときに、Last-Modifiedを作る必要があって。
で、
http://www.studyinghttp.net/header#Last-Modified
を読んでたらHTTP-Dateというのが出てきて、
http://www.studyinghttp.net/header#HTTP-Date
を読んでたら"GMT表記"が必要らしい。

今まであまり気にしてきませんでしたが、Last-Modified や If-Modified-Since は特に画像などをPHPでブリッジして出力させるとき、パケット量を抑える為に必須です。である以上、それなりにきっちりしておかないと、せっかく実装してもGMT関連の認識ズレで304が返せない・・・ってなことにもなりかねません。

で、基本。

DOS>php -r "echo mktime(0, 0, 0, 1, 1, 1970);"
Warning: mktime(): Windows does not support negative values for this
function in Command line code on line 1
-1
DOS>php -r "echo mktime(9, 0, 0, 1, 1, 1970);"
0
DOS>php -r "echo gmmktime(9, 0, 0, 1, 1, 1970);"
32400

ええっと、つまり、mktimeは「その地域での時刻表記→GMTでは何秒経過しているか」を算出。
で、gmmktimeは「今いる場所をGMTとして、今の時刻表記をそのままGMTでは何秒経過しているか」を算出。
だから、

32400 = 3600 * 9

つまり9時間分、ずれているわけ。

DOS>php -r "echo strftime('%a, %d %b %Y %H:%M:%S', mktime(9, 0, 0, 1, 1,1970));"
Thu, 01 Jan 1970 09:00:00

→これは、mktime()は・・・0を返す。つまり、日本時間で9時というのは、GMTでは0
秒ということ。
で、strftimeの引数は、GMTでのタイムスタンプ。つまり、0秒→GMTでの0秒→当然、
日本時間では9時。

DOS>php -r "echo gmstrftime('%a, %d %b %Y %H:%M:%S', mktime(9, 0, 0,1, 1, 1970));"
Thu, 01 Jan 1970 00:00:00

→gmstrftimeの引数も当然GMTでのタイムスタンプ。ただし、表記した結果はGMTでの
表記になる。
つまり、0秒→GMTでの0秒→GMTでの表記になるから、当然、00:00:00.

DOS>php -r "echo strftime('%a, %d %b %Y %H:%M:%S', gmmktime(9, 0, 0,1, 1, 1970));"
Thu, 01 Jan 1970 18:00:00

→これは間違えたパターン。gmmktimeで返されるのは、引数をGMTとみなしたときの秒数。つまり、9*3600が返される。
で、これをそのままGMTでの9*3600と考えたので、strftimeは日本時間に直すときにさらに9時間足すため、18時になる。

DOS>php -r "echo gmstrftime('%a, %d %b %Y %H:%M:%S', gmmktime(9, 0, 0, 1, 1, 1970));"
Thu, 01 Jan 1970 09:00:00

→これは、IN/OUT両方ともGMTでそろえた場合。引数にはGMTでの時間を渡し、GMTでの秒が返され、gmstrftimeではGMTでの秒数として受け取り、GMTでの表記で出力している。

こう考えると、引数や返り値の"timestamp"はあくまでも"GMT「としてみなされる」"ことが暗黙の前提と考えてよいような気がする。
例えば、2007-04-25 18:15:XX付近で以下のコードを実行してみる。

DOS>php -r "echo gmmktime(18, 15, 0, 4, 25, 2007);"
1177524900
DOS>php -r "echo time();"
1177492531

これ、コマンドラインで実行する時差を補正すれば、ちょうど9時間ずれている。逆に、mktime()だとちょうど同じ。
ようするに、time()は、現在のロケールと同時点でのGMTの秒数を返す。
つまり、ロケールに基づく時差をZとし、現在ロケールの時刻表現をargとすれば、

mktime = arg - Z = time()
gmmktime = arg = time() + Z

よって、以下になる。

DOS>php -r "echo gmmktime(18, 15, 0, 4, 25, 2007) -  mktime(18, 15, 0, 4, 25, 2007);"
32400(=9 * 3600)
(= arg - (arg - Z))

通常のmktimeやstrftimeが、内部的にZを補正するのは・・・time()の挙動に引きずられているとみなせる。
time()自体はGMT秒数を出力するため、常に GMT となる。

strftimeを、f(ARG) = ARG + Z として定義すれば、

strftime(GMT) = GMT + Z

となり、現在ロケールでの表記が取得できる。ここで、

X(ARG) = strftime(mktime(ARG))

とすれば、

X(ARG) = mktime(ARG) + Z = ARG - Z + Z = ARG

として、最初にmktimeに渡した、現在ロケールに基づくタイムスタンプと同一の、文字表現が取得できる。

"同時点"というのがキーワードになる。
mktime, strftimeは、結局"同時点"でのGMTを返したり、引数にとる。
gmktime, gmstrftimeは、同時点補正を行わない。つまり、今いる位置がグリニッジと想定する。
逆に言えば、"同時点でのGMTでの表記がほしい!"となれば?time()はGMT時間を返す。
あとはそれをそのまま、グリニッジにいると思わせればよいので、gmstrftimeに mktime() か time() を食わせればよい。

しかしこれ、実際にHTTP Headerで使うとしたら、ブラウザ側どうして来るんだろうな・・・。
結局"同時点でのGMT"を中心に動かすわけで・・・動くんだよな・・・。

echo strftime('%a, %d %b %Y %H:%M:%S GMT', mktime(9, 0, 0, 1, 1, 1970));
(→PHP4.3.6 on Windowsだと、%T(=%H:%M:%S)が認識されなかった)
Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2009-03-29 23:00:57
md5:7de3fe0e9351c444d350346a6e1f49a1
sha1:ee59fced5976b392479b9a10d2d7946eaf6e5bdd
コメント
コメントを投稿するにはログインして下さい。