サンプル・プログラムの実行例
サンプル・プログラムのダウンロード
RFC3339.php | サンプル・プログラム本体 |
解説:UNIX時間をUTCに変換
UNIXタイムスタンプは、UNIX epoch(1970年1月1日 0時0分0秒)を0とする秒数である。これを UTC に変換するには、組み込み関数 gmdate を使う。
ISO 8601 形式のUTC表示は、「年:月:日T時:分:秒Z」である。年は西暦、時は24時制である。月、日、時、分、秒が1桁であるときには2桁目を0で埋める(ゼロサプレス)。
135: /**
136: * UNIXタイムスタンプからRFC3339 UTC タイムスタンプを返す
137: * @param int $unix UNIXタイムスタンプ
138: * Unix epoch(1970年1月1日 00:00:00 GMT))からの通算秒
139: * @return ISO 8601(RFC 3339) UTC
140: */
141: function unix2utc($unix) {
142: return (gmdate('Y-m-d', $unix) . 'T' . gmdate('H:i:s', $unix) . 'Z');
143: }
解説:UTCをローカル時間に変換
1番目の引き数として ISO 8601 の UTC、2番目の引数としてローカル時間とUTCとの差(時)、3番目の引数としてローカル時間とUTCの差(分)を指定する。3番目の引数は省略可能である。
ISO 8601 のローカル時間表記は、「年:月:日T時:分:秒±UTCとの差(時):UTCとの差(分)」である。規格上、UTCの時、分、秒は省略可能であるので、省略された場合の処理が回りくどくなっている。
UTC は、いったんUNIXタイムスタンプに戻し、あらためてローカル時間表記に変換する。
145: /**
146: * ISO 8601(RFC 3339) UTC タイムスタンプをローカルのタイムスタンプに変換する
147: * @param string $utc ISO 8601(RFC 3339) UTCタイムスタンプ
148: * @param int $tz_hour タイムゾーン(UTCと地方時の差;時)
149: * @param int $tz_min タイムゾーン(分:省略時=0)
150: * @return string ローカルのタイムスタンプ(ISO 8601(RFC 3339)表記)
151: * NULL=エラー(入力文字列が規定外など)
152: */
153: function utc2local($utc, $tz_hour, $tz_min=0) {
154: $tz_hour = func_get_arg(1);
155: //可変長変数を使う
156: $tz_min = (@func_num_args() >= 3) ? func_get_arg(2) : (0);
157:
158: if (preg_match('/[0-9]+\-[0-9]+\-[0-9]+T[0-9]+\:[0-9]+\:[0-9]+Z/i', $utc) == 1) {
159: list($year, $month, $day, $hour, $minuite, $second) = sscanf($utc, '%d-%d-%dT%d:%d:%dZ');
160: } else if (preg_match('/[0-9]+\-[0-9]+\-[0-9]+T[0-9]+\:[0-9]+Z/i', $utc) == 1) {
161: list($year, $month, $day, $hour, $minuite) = sscanf($utc, '%d-%d-%dT%d:%dZ');
162: $second = 0;
163: } else if (preg_match('/[0-9]+\-[0-9]+\-[0-9]+T[0-9]+Z/i', $utc) == 1) {
164: list($year, $month, $day, $hour, $minuite) = sscanf($utc, '%d-%d-%dT%dZ');
165: $minuite = 0; $second = 0;
166: } else if (preg_match('/[0-9]+\-[0-9]+\-[0-9]+Z/', $utc) == 1) {
167: list($year, $month, $day, $hour, $minuite) = sscanf($utc, '%d-%d-%dZ');
168: $hour = 0; $minuite = 0; $second = 0;
169: } else {
170: return NULL; //UTC書式エラー
171: }
172:
173: $tt = mktime($hour + $tz_hour, $minuite + $tz_min, $second, $month, $day, $year);
174:
175: $s = date('Y-m-d', $tt) . 'T' . date('H:i:s', $tt);
176: $f = ($tz_hour < 0) ? '-' : '+';
177:
178: return sprintf('%s%s%02d:%02d', $s, $f, abs($tz_hour), $tz_min);
179: }
解説:メインプログラム
241: // メインプログラム ============================================================
242: $utc = unix2utc(time()); //内蔵時計の日時をUTCに変換する
243: $tz_hour = date('Z') / (60 * 60); //タイムゾーン(時)
244: $tz_name = date('T'); //タイムゾーン略称
245: $local = utc2local($utc, $tz_hour); //JST = UTC + 09:00
246: $errmsg = ($local == NULL) ? 'ローカル時間が計算できない' : '';
247:
248: $HtmlBody = makeCommonBody($utc, $local, $tz_name, $errmsg);
249:
250: // 表示処理
251: echo $HtmlHeader;
252: echo $HtmlBody;
253: echo $HtmlFooter;
ローカル時間とのタイムゾーンは、組み込み関数 date に引数 'Z' を与えることで求めることができる。また、タームゾーンの略称は、 date に引数 'T' を与えることで求めることができる。
なお、 date に引数 'c' を与えることで、ISO 8601 形式のローカル時間を求めることができるが、これはPHP 5で加わった機能なので、今回は使用を見送りにした。
ここで、timeの代わりに組み込み関数 filemtime を使えば、ファイルのタイムスタンプ(最終更新日時)を ISO 8601 にすることができる。
余談になるが、標準関数 mktime の引き数の順番は、時,分,秒,月,日,年だが、年の部分は2桁または4桁の西暦年号を代入する。2桁の場合、 0~69 の間の値は 2000~2069 に、70~100 は 1970~2000 にマッピングされる。
参考サイト
- タイムスタンプの必要性:ぱふぅ家のホームページ
- 国際原子時と協定世界時:ぱふぅ家のホームページ
- PHPでRFC3339形式のタイムスタンプを解釈する:ぱふぅ家のホームページ
- RFC 3339(和訳)
コンテンツの中にある時刻表記は、クライアントPCが置かれている地域の現地時間なのか、それともサーバが置かれている地域の現地時間なのか、はたまた世界標準時なのか――タイムゾーン(世界標準時間と地方時間の差)を明らかにする必要がある。
そこで今回は、与えた日時をインターネットの標準形式である ISO 8601形式で表示するプログラムを紹介する。
ISO 8601 形式は RFC 3339 とほぼ同じ内容である。日本では、JIS X 0301 として規格化されている。
(2021年3月27日)PHP8対応,リファラ・チェック改良。
(2019年5月4日)JST以外にも対応した(タイムゾーン汎用)。