線上的服務有世界各地的人來使用(若是有提供英文語系的話), 就有可能遇到需要幫世界各地的時區算時間.
要做個時區分佈設定(ex: 台灣是 +8), 想要選取後, 自動秀出他的時間, 照理說就是現在時間 -8hr 即可(設定於台灣機器而言), 但是又想到機器可能會換, 程式還是該寫好點才行, 於是花了點時間做研究.
本來想用 PHP 時間轉換 By 地區
這個來搞定, 要寫時才發現不曉得各時區的地區名稱等, 用這個反而累. XD
研究時找到兩個 PHP function, 先記著, 之後可以搭配著用:
- 列出全部區域的名稱 - timezone_abbreviations_list()
- 列出全部區域的名稱、日光節約時間(DST)多久、離 GMT 差多久. - listAbbreviations()
列出全部區域的名稱 - timezone_abbreviations_list()
<?php $timezone_identifiers = DateTimeZone::listIdentifiers(); print_r($timezone_identifiers); ?>
列出全部區域的名稱、日光節約時間(DST)多久、離 UTC 差多久. - listAbbreviations()
<?php $timezone_abbreviations = DateTimeZone::listAbbreviations(); print_r($timezone_abbreviations); ?>
藉由這次研究, 特別是 GMT / UTC 等時間, 靠下述兩篇 Wikipedia 的文章, 觀念也清楚不少.
名詞解釋
- UTC: Coordinated Universal Time 協調世界時是以原子時秒長為基礎,在時刻上盡量接近於世界時的一種時間計量系統。
- GMT: Greenwich Mean Time 格林威治標準時間,例如台北為 GMT + 8 就是台北的時區為格林威治標準時間 + 8 個小時。
- DST: Daylight Saving Time 就是指該地區正在施行日光節約的夏令時間,也就是當地標準時間 + 1 個小時。
於是, 要算當地時間的話, 需要先在取得機器的 UTC 時間, 再去換算成當地時間就可以了.
以台灣地區為例, 要取得 UTC 的時差:
- 測試: 執行 gmmktime(0, 0, 0, 1, 1, 1970) 得到 0, 再執行 mktime(0, 0, 0, 1, 1, 1970) 得到 -28800 = -8hr.
- 現在機器在台灣, 但是台灣的時區(Time zone)比 UTC 時間快 8小時, 所以上面 mktime(0, 0, 0, 1, 1, 1970); 會是 -8hr.
程式:
<?php echo gmmktime(0, 0, 0, 1, 1, 1970); // 0 echo mktime(0, 0, 0, 1, 1, 1970); // -28800secs = -8hr ?>
將相關的 PHP function 都拿來測試, 測取得 UTC 的方法, 有下述這幾類. (最下面那欄 UTC 是錯誤的)
<?php echo "======================\n"; echo 'UTC 1970: ' . gmmktime(0, 0, 0, 1, 1, 1970) . "\n"; // 0 echo 'TW 1970: ' . mktime(0, 0, 0, 1, 1, 1970) . "\n"; // -28800secs = -8hr echo "======================\n"; $t = time() + mktime(0, 0, 0, 1, 1, 1970); echo 'UTC Timestamp: ' . $t . "\n"; // 1236129510 echo 'TW Timestamp: ' . time() . "\n"; // 1236158310 echo "======================\n"; // gmstrftime("%b %d %Y %H:%M:%S", mktime(date('H,i,s,n,j,Y'))); echo 'UTC: ' . gmstrftime("%b %d %Y %H:%M:%S") . "\n"; // UTC: Mar 04 2009 09:08:47 echo 'TW: ' . strftime("%b %d %Y %H:%M:%S") . "\n"; // TW: Mar 04 2009 17:08:47 echo "======================\n"; echo 'UTC: ' . date('Y-m-d H:i:s', time() + mktime(0, 0, 0, 1, 1, 1970)) . "\n"; // UTC: 2009-03-04 09:08:47 echo 'TW: ' . date('Y-m-d H:i:s') . "\n"; // TW: 2009-03-04 17:08:47 echo "======================\n"; echo 'UTC: ' . date('Y-m-d H:i:s', gmmktime(date('H, i, s, n, j, Y'))) . " - error\n"; // UTC: 2009-03-05 01:08:47 echo 'TW: ' . date('Y-m-d H:i:s', mktime(date('H, i, s, n, j, Y'))) . "\n"; // TW: 2009-03-04 17:08:47 echo "======================\n"; ?>
由上述可得到, 要取得 UTC 的時間, 用此方法運算即可: time() + mktime(0, 0, 0, 1, 1, 1970);
於是寫兩個 Function 來做, 取得 UTC 時間 和 傳入地區時間, 算出當地時間(此 function 並未考慮 DST 的時間).
<?php function get_utc_timestamp() { return time() + mktime(0, 0, 0, 1, 1, 1970); } function get_timestamp_from_timezone($tz_offset = 0) { if ($tz_offset > 14 || $tz_offset < -12) $tz_offset = 0; // timezone offset range: -12 ~ 14 return time() + mktime(0, 0, 0, 1, 1, 1970) + ($tz_offset * 60 * 60); } /* Test */ echo 'UTC: ' . date('Y-m-d H:i:s', get_timestamp_from_timezone()) . "\n"; echo 'TW: ' . date('Y-m-d H:i:s', get_timestamp_from_timezone(8)) . "\n"; echo '-8: ' . date('Y-m-d H:i:s', get_timestamp_from_timezone(-8)) . "\n"; ?>
世界時間 測試對照
下述網站有時區對照, 可以知道世界各地目前時間, 再藉此跟上述程式去做些比對囉~ 🙂