0
<?php
    $saturday = array(
        '00:00 - 01:00' => 'Nightshow',
        '01:00 - 02:00' => 'Nightshow',
        '02:00 - 03:00' => 'Nightshow',
        '03:00 - 04:00' => 'Nightshow',
        '04:00 - 05:00' => 'Nightshow',
        '05:00 - 06:00' => 'Early birds',
        '06:00 - 07:00' => 'Early birds',
        '07:00 - 08:00' => 'Cox n Crendor in the morning',
        '08:00 - 09:00' => 'Cox n Crendor in the morning',

        ...

        '23:00 - 24:00' => 'John late night'
    );


    foreach($saturday as $timeD => $show){
        if(!empty($timeD) && isset($timeD)){
            $timesplit = explode(' -', $timeD);

            if (time() > strtotime('today '. $timesplit[0]) && time() < strtotime('today '. $timesplit[1])) {

                echo $show;
            }
        }
    }
?>

再次您好 Stackoverflow!

我有一个数组,其中包含代表时间表的一天中的时间(24 小时格式)。我正在尝试做的是检查当前正在播放的节目。我在上面尝试过的方法不起作用 - 时间结果是几个小时的时间,否则它们将完全错误,甚至没有按特定顺序。我不明白出了什么问题。我该如何解决这个问题?

提前致谢!

4

2 回答 2

3

我相信您遇到了一些基本的时区问题。

时区基本

时区转换可能会令人沮丧,但一旦你习惯了它,它就会变得非常简单。

当我们处理时间时,我们还需要小心使用 和 之类的strtotime()函数date()。这两个功能时区设置的影响。当我说时区设置时,我指的是date.timezonephp.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')

现在将为您提供1360022400UTC 时间,或者恰好是 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.


我希望这不会太令人困惑,但处理所有这些数学真的很有趣。

于 2013-09-21T12:14:09.453 回答
1

(稍后您将不得不在脚本中替换$fake_timestamp为当前时间戳time()……但我需要以这种方式进行测试。)

<?php


    $saturday = array(
        '00:00 - 01:00' => 'Nightshow',
        '01:00 - 02:00' => 'Nightshow',
        '02:00 - 03:00' => 'Nightshow',
        '03:00 - 04:00' => 'Nightshow',
        '04:00 - 05:00' => 'Nightshow',
        '05:00 - 06:00' => 'Early birds',
        '06:00 - 07:00' => 'Early birds',
        '07:00 - 08:00' => 'Cox n Crendor in the morning',
        '08:00 - 09:00' => 'Cox n Crendor in the morning',
        '23:00 - 24:00' => 'John late night'
    );

    //$current_day_timestamp = gettimeofday(); //bug? returns time(), not day!time
    $current_day_timestamp = strtotime('TODAY');
    //print 'Current day time: '.$current_day_timestamp.'<br />';

    //Trying to "find" Early birds 05:00-06.00, setting "current time" to 05:30
    $fake_timestamp = $current_day_timestamp + 5.5 * 3600;
    //print 'fake time: '.$fake_timestamp.'<br />';

    foreach ($saturday AS $hours => $show) {
      $hours = explode(' - ', $hours);
      $show_start = strtotime($hours[0]);
      $show_end = strtotime($hours[1]);
      if ($show_start < $fake_timestamp AND $show_end > $fake_timestamp) {
        print $show;
      }
      //print $show.'<hr />';
      //print 'show start: '.$show_start.'<br />';
      //print 'show end: '.$show_end.'<br /><br />';
    }

?>
于 2013-09-21T10:59:45.570 回答