2017-02-15 5 views
3

Я пытаюсь выполнить функцию, которая вернет true, если сейчас в настоящее время между определенными часами и днями недели.PHP Datetime Объект с более ранним временем datetime имеет более высокую временную метку?

Вещь, временные метки 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 

Почему это $ мин метка времени больше, чем $ сейчас?

Я бегу PHP 5.6.30

+0

Вы уверены в этом? Первая временная метка, указанная '1487164620',' 2017-02-15 13: 17: 00' - но в UTC Time. Итак, будет 07:30 в EST, что на самом деле меньше, чем 'min'. Я не могу воспроизвести это, ваш код работает должным образом. – dognose

+0

@dognose Я воспроизвел его https://3v4l.org/YtC7u – Machavity

+0

смешная вещь я не могу воспроизвести ее для php 5.6.30: https://3v4l.org/VDETE – pycvalade

ответ

0

Docu утверждает, что вы не должны использовать EST, с предупреждением о "странных" эффектов:

Warning Please do not use any of the timezones listed here (besides UTC), they only exist for backward compatible reasons, and may expose erroneous behavior.

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

Running свой сниппет с правильным названием часового пояса, например 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) 

Использование Америка/Триатлон: 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) 

(в то время как все должно быть verysame метка времени, сравнить с линией 2)

+0

Я думаю, что ты действительно прав! Использование Canada/Eastern фактически заставляет его работать. Благодаря! – pycvalade

+0

@JacobS 5.4.16 работает также с EST. Я не могу найти списки изменений, но я помню, что удаление некоторых сокращений в часовом поясе было указано где-то ... Итак, я считаю, что для более поздних версий «фракция» кода все еще может обрабатывать EST, в то время как другие части могут " t, что ведет к этому странному поведению. – dognose

+0

@pycvalade Но 'Канада/Восточная' также указана на странице НЕ ИСПОЛЬЗУЮТ ... Итак, вам лучше найти что-то еще, что я бы сказал, например« Америка/Торонто »: P – dognose

0

settimezone делает не изменяйте базовую метку времени, только формат отображения для метки времени.

В результате вы создали дату и время в GMT. Это означает, что временная метка от GMT. Затем вы изменили часовой пояс так, чтобы он отображал время в EST, но фактическое время по-прежнему сохраняется с GMT.

Затем вы создаете новое datetime в EST и задаете время в EST. Фактическое базовое время/метка времени - от EST. Затем вы продублировали этот процесс.

В результате у вас есть метки времени UTC, созданные с одного времени по Гринвичу (сейчас) и два времени EST (мин/макс).

Редактировать: Вывод: DateTime :: setTimeZone влияет только на визуальное отображение времени. Он не меняет момент времени, в который он ссылается, когда он был создан.

Second Edit: Я не могу воспроизвести проблему. Это может быть ошибка в версии PHP, которую вы используете, но формат ('U') должен указывать правильную временную метку unix для форматированного времени, которое вы используете. Это явно не так, потому что ваша временная метка теперь совпадает с тем, что было бы в GMT, а не в EST.

+0

Мысль о том, что первая, а также - но unix-timestamp - это «unix time». Он не заботится о часовом поясе. setTimeZone ofc. не меняет Точку во времени - потому что это то же самое место во времени повсюду. – dognose

+0

Это не меняет момент времени. 8:30 -0600 приходит после 13:10 -0000 каждый день каждую неделю. Изменить: Если у вас возникли проблемы с этим. 8:30 -0600 - 14:30 GMT. 13:10 GMT - до 14:30 по Гринвичу. –

+0

См. Изменение в моем ответе, чтобы сделать реальную проблему «чистой». Оба результата должны быть равны, только случай с использованием EST дает неправильный результат. (Он отображает правильное время, но обрабатывает временную метку, как если бы это время было временем UTC) – dognose

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 

suggestion note: $now->format('U') gives you wrong timestamp, for actual timestamp you need to retrieve it via $now->getTimestamp() it must be equal original timestamp.

+0

Для справки, -> getTimestamp всегда будет давать исходную временную метку, с которой был создан DateTime, или в последний раз, когда был установлен. Он не будет правильно отражать изменения в часовом поясе. формат должен (или «должен») дать правильную временную метку для отображаемого времени. –

+1

imo, это немного неправильно ... timestamp должна быть одинаковой каждый раз для каждого часового пояса, но настройки часового пояса будут влиять на формат .. но nvm, это только мое imo – Wizard

+0

@Wizard Согласен, отметка времени никогда не должна изменяться, независимо от того, какой часовой пояс вы установили. (Временные метки UTC по дизайну) – dognose