PHP 查詢並算出世界各地時間

線上的服務有世界各地的人來使用(若是有提供英文語系的話), 就有可能遇到需要幫世界各地的時區算時間.

要做個時區分佈設定(ex: 台灣是 +8), 想要選取後, 自動秀出他的時間, 照理說就是現在時間 -8hr 即可(設定於台灣機器而言), 但是又想到機器可能會換, 程式還是該寫好點才行, 於是花了點時間做研究.

本來想用 PHP 時間轉換 By 地區 這個來搞定, 要寫時才發現不曉得各時區的地區名稱等, 用這個反而累. XD

研究時找到兩個 PHP function, 先記著, 之後可以搭配著用:

列出全部區域的名稱 - 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";
?>

世界時間 測試對照

下述網站有時區對照, 可以知道世界各地目前時間, 再藉此跟上述程式去做些比對囉~ 🙂

作者: Tsung

對新奇的事物都很有興趣, 喜歡簡單的東西, 過簡單的生活.

發表迴響

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料