具有早期日期时间的PHP Datetime对象具有更高的时间戳值?

时间:2017-02-15 18:19:03

标签: php datetime timezone

我尝试执行的功能如果现在是在一周的某些时段和几天之间,则会返回true。

事情是,unix时间戳似乎不匹配。

<?php
function isWorkingTime() {
  $now = new DateTime(date('Y-m-d H:i:00'), new DateTimeZone(date('T')));

  $tz = $now->getTimezone();
  if(strtolower($tz->getName()) != 'est'){
    $now->setTimezone(new DateTimeZone('EST'));
  }

  $min = clone $now;
  $min->setTime(8,30,0);

  $max = clone $now;
  switch($now->format('N')){
    case 1:
    case 2:
    case 3:
    case 4:
      $max->setTime(17,30,0);
      break;
    case 5:
      $max->setTime(16,30,0);
      break;
    default:
      return false;
      break;
  }

  return ($now >= $min && $now < $max);
}
?>

如果我继续尝试输出3个日期时间对象,如下所示:

<?php
echo 'now: '.$now->format('Y-m-d H:i:s U T').PHP_EOL;
echo 'min: '.$min->format('Y-m-d H:i:s U T').PHP_EOL;
echo 'max: '.$max->format('Y-m-d H:i:s U T').PHP_EOL;
?>

我明白了:

now: 2017-02-15 13:17:00 1487164620 EST
min: 2017-02-15 08:30:00 1487165400 EST
max: 2017-02-15 17:30:00 1487197800 EST

为什么$ min的时间戳大于$ now?

我正在运行PHP 5.6.30

3 个答案:

答案 0 :(得分:0)

该文件声明您不应使用EST,并警告“奇怪”效果:

  

警告请不要使用此处列出的任何时区(此外   UTC),它们仅出于向后兼容的原因而存在,并且可能会暴露   错误的行为。

http://php.net/manual/en/timezones.others.php

使用适当的时区名称America/New_York运行您的代码段不会显示此问题:https://3v4l.org/NR3cg

要清楚问题/错误:

使用EST: https://3v4l.org/BdUan

02/15/2017 6:00 am 1487138400 -> TS says 02/15/2017 @ 6:00am (UTC) (wrong)
02/15/2017 8:30 am 1487165400 -> TS says 02/15/2017 @ 1:30pm (UTC) (right)

使用America / New_York: https://3v4l.org/ndISv

02/15/2017 6:00 am 1487156400 -> TS says 02/15/2017 @ 11:00am (UTC) (right)
02/15/2017 8:30 am 1487165400 -> TS says 02/15/2017 @ 1:30pm (UTC) (right)

(虽然一切都应该是真实时间戳,与第2行比较)

答案 1 :(得分:0)

settimezone不会更改基础时间戳,只会更改时间戳的显示格式。

结果是,您在GMT中创建了一个日期时间。这意味着时间戳来自GMT。然后你更改了时区,以便在EST中显示时间,但实际时间仍然是GMT。

然后在EST中创建一个新的日期时间并在EST 中设置时间。实际的基础时间/时间戳来自EST。然后你复制了这个过程。

结果是您从一个GMT时间(现在)和两个EST时间(最小/最大)创建了UTC时间戳。

编辑: 需要注意的是,DateTime :: setTimeZone仅影响时间的可视化显示方式。它不会改变它在创建时的时间点。

第二次编辑: 我无法复制这个问题。这可能是您运行的PHP版本中的错误,但格式(&#39; U&#39;)应为您使用的格式化时间提供正确的unix时间戳。显然不是这样,因为你现在的时间戳与GMT而不是EST相匹配。

答案 2 :(得分:0)

我可能错了,但在你的情况下,似乎你需要在setTime()之后再次设置时区:

<?php
$now = new DateTime(date('Y-m-d H:i:00'), new DateTimeZone(date('T')));
echo '          original: '.$now->format('Y-m-d H:i:s U T').PHP_EOL;
$now->setTimezone(new DateTimeZone('EST'));
echo '    after timezone: '.$now->format('Y-m-d H:i:s U T').PHP_EOL;
$now->setTime(8,30,0);
echo '     after settime: '.$now->format('Y-m-d H:i:s U T').PHP_EOL;
$now->setTimezone(new DateTimeZone('EST'));
echo 'after 2nd timezone: '.$now->format('Y-m-d H:i:s U T').PHP_EOL;

结果:

          original: 2017-02-15 22:44:00 1487187840 MSK
    after timezone: 2017-02-15 14:44:00 1487169840 EST
     after settime: 2017-02-15 08:30:00 1487165400 EST
after 2nd timezone: 2017-02-15 08:30:00 1487147400 EST
  

建议说明:$now->format('U')为您提供了错误的时间戳,对于您需要通过$now->getTimestamp()检索它的实际时间戳,它必须等于原始时间戳。