我相信您遇到了一些基本的时区问题。
时区基本
时区转换可能会令人沮丧,但一旦你习惯了它,它就会变得非常简单。
当我们处理时间时,我们还需要小心使用 和 之类的strtotime()
函数date()
。这两个功能受时区设置的影响。当我说时区设置时,我指的是date.timezone
php.ini 中的值。
举个例子,我设置date.timezone = Asia/Singapore
了 UTC+8 时区:
假设现在是 UTC 时间2013-02-05 00:00:00 UTC
,时间戳应该是1360022400
:
time()
会给我1360022400
strtotime('2013-02-05 00:00:00')
会给我1359993600
(或-28800,或-8小时!)
注意strtotime
行为方式?它实际上使用了 PHP 环境位于 UTC+8 时区的事实,并认为您指定的日期时间位于 +8 时区,因此它为您推迟了 8 小时,以正确地以 UTC 时间戳表示它。这就是问题所在。
解决方案
通常,我会做的(也许有人可以提供更好的解决方案?)是UTC
在模棱两可的日期时间后面硬附加一个并迫使我们在 UTC 时区计算所有内容。所以只需这样做:
strtotime('2013-02-05 00:00:00 UTC')
现在将为您提供1360022400
UTC 时间,或者恰好是 00:00:00。time()
当您在返回真正的 UTC 时间戳时进行时间敏感计算时,这尤其有用。
一些注意事项:
time()
无论时区设置如何,都会始终为您提供 UTC 时间戳。
strtotime()
将始终受到时区设置的影响,因此如果您进行时间敏感比较,请尝试确保它们都使用 UTC。
date()
同样,受时区设置的影响,date('Y-m-d H:i:s', 1360022400)
将在哪里为您提供2013-02-05 08:00:00
并克服这一点,我们改为使用。gmdate
('Y-m-d H:i:s', 1360022400)
你的问题
因此,由于您似乎在这里处理时间敏感的决定,一个问题,如果我与您住在不同的时区,我是否需要看到与您相同的结果?
如果我们(我和你)需要看到完全相同的结果,那么你应该这样做:
//Let's say the timezone required for that decision made is UTC+6
$event_timezone_offset = 6 * 3600;
foreach($saturday as $timeD => $show){
if(!empty($timeD)){ //you don't need isset here as !empty taken care of it
list($startTime, $endTime) = explode(' - ', $timeD);
$start = strtotime('today '.$startTime.' UTC') - $event_timezone_offset;
$end = strtotime('today '.$endTime.' UTC') - $event_timezone_offset;
$now = time();
if ($start <= $now && $now < $end) { //notice the inclusive <=
echo $show;
}
}
对于 line strtotime('today '.$startTime.' UTC') - $event_timezone_offset;
,让我们单步执行:
假设现在是当地时间07:00 (UTC+6)
,您应该看到“Cox n Crendor..”:
time()
将为您提供确切的 UTC 时间戳2013-09-21 01:00:00 UTC
strtotime('today 07:00 UTC')
会给你时间戳2013-09-21 07:00:00 UTC
- 一旦你这样做
- $event_timezone_offset
了,你就会得到一个时间2013-09-21 01:00:00 UTC
- 那么这
if ($start <= $now)
将是真的,你应该看到'Cox n Crendor..'
如果我和你需要根据我们各自的本地时间戳得到不同的结果,那么你需要使用 javascript 嗅探用户的时区,或者要求他们通过一些后端设置来设置时区,并使用相同的逻辑来确定结果, 通过设置$event_timezone_offset = $user_timezone_offset
.
我希望这不会太令人困惑,但处理所有这些数学真的很有趣。