在线的服务有世界各地的人来使用(若是有提供英文语系的话), 就有可能遇到需要帮世界各地的时区算时间.
要做个时区分布设置(ex: 台湾是 +8), 想要选取后, 自动秀出他的时间, 照理说就是现在时间 -8hr 即可(设置于台湾机器而言), 但是又想到机器可能会换, 程序还是该写好点才行, 于是花了点时间做研究.
本来想用
研究时找到两个 PHP function, 先记着, 之后可以搭配着用:
列出全部区域的名称 - timezone_abbreviations_list()
$timezone_identifiers = DateTimeZone::listIdentifiers();
print_r($timezone_identifiers);
?>
列出全部区域的名称、日光节约时间(DST)多久、离 UTC 差多久. - listAbbreviations()
$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.
程序:
echo gmmktime(0, 0, 0, 1, 1, 1970); // 0
echo mktime(0, 0, 0, 1, 1, 1970); // -28800secs = -8hr
?>
将相关的 PHP function 都拿来测试, 测取得 UTC 的方法, 有下述这几类. (最下面那栏 UTC 是错误的)
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 的时间).
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";
?>
世界时间 测试对照
下述网站有时区对照, 可以知道世界各地目前时间, 再借此跟上述程序去做些比对啰~