Вопрос по php, timezone, datetime – DateTime :: diff () не зависит от часового пояса, но всегда возвращает одно и то же значение

0

Я добавляю данные аукциона в свою систему. Например:

user's timezone  is : `America/Denver`
auction start time is : Thu, 21 Jun 2012 03:46:22 AM
auction period : 1 day.
auction end time : Fri, 22 Jun 2012 03:46:22 AM

Я храню всю эту информацию, как она есть в моей БД (т.е.all stored time based on user's timezone).

Теперь я хочу актуальныйdifference between end time and current time (из Америки / часовой пояс Денвера).

я использовалDateTime() функции

so even I don't convert the timezone; it returns same difference (and that is wrong too).

Мой код PHP ниже; Вы также можете найти его наCodePad

$end_time = 'Fri, 22 Jun 2012 03:46:22 AM';
$tz = 'America/Denver';
dateDifference($end_time,$tz);

function dateDifference($end, $tz = NULL)
    {
      $owner_tz = new DateTimeZone($tz);
      //var_dump($owner_tz->getName()); 

      $from  = new DateTime("now", new DateTimeZone('GMT'));     
      $from ->setTimeZone($owner_tz);

      $to = new DateTime($end,new DateTimeZone('GMT'));
      /* @Note:I have commented below setTimeZone() because I have already stored 
       * `end time` as per user's  timezone, So I dont need to convert it again 
       * into user's timezone.you can un-comment below line. 
       * it doesn't affect the results anyways.
       */
     //$to ->setTimeZone($owner_tz);        

    //procedural style using date_diff()
    $interval = date_diff($from, $to);        
    var_dump($interval); 

    // OO style using dateTime::diff()
    $interval = $from->diff($to);       
    var_dump($interval);     
}

Возвращает:

object(DateInterval)[4]
  public 'y' => int 0
  public 'm' => int 0
  public 'd' => int 0
  public 'h' => int 16
  public 'i' => int 40
  public 's' => int 24
  public 'invert' => int 0
  public 'days' => int 6015

References:

DateTime() DateTime::diff DateTime::setTimeZone Handling timezone conversion with PHP DateTime
но вот почемуdate_diff отображать неверные результаты ?? diEcho
Хранение информации о дате / времени на основе часового пояса пользователя - очень плохая практика, что если пользователь изменил свой часовой пояс? Хорошей практикой является хранение всей информации о дате / времени БЕЗ часового пояса (например, отметка времени UTC), таким образом вы можете минимизировать количество операций преобразования и вычисления, поэтому вам нужно только беспокоиться об установке правильного часового пояса при выводе даты / времени в пользователь. Melvin
Я не говорю, что вам нужно изменить свое заявление, это всего лишь предложение. Вы поместили date_default_timezone_set куда-нибудь, чтобы убедиться, что время на вашем сервере правильное? Melvin
мой тип данных столбцаdatetime Итак, какие изменения мне нужно сделать, когда я сохраняю данные о дате и времени в качестве часового пояса пользователя? diEcho
да, я установил его в моем конфигурационном файле. но твоя идея действительно хороша. я подслушал эту мысль раньше diEcho

Ваш Ответ

2   ответа
0

Я получил решение, поэтому я хотел бы поделиться

На самом деле я установил часовой пояс по умолчанию вconfig.inc.php файл, как показано ниже

date_default_timezone_set('America/Los_Angeles');

тогда я проверяюcurrent time and timezone of MySQL server из phpmyadmin с запросом ниже

SELECT NOW(), SYSDATE(), @@global.time_zone , @@session.time_zone , 
      TIMEDIFF( NOW( ) , CONVERT_TZ( NOW( ) , @@session.time_zone ,  '+00:00' )) 
      AS OFFSET

Это вернутьOFFSET значение+05:30

solution steps:

  • First I changed the timezone of mySQL Server to GMT/UTC +00:00 ( I have super privilage on mySQL server)

    SET GLOBAL time_zone = '+00:00';  
    
  • We save the date and time using start_date = NOW() ( column datatype: DATETIME )

Теперь есть 2 способа получить дату и время в соответствии с часовым поясом пользователя (America/Denver)

first method ( using PHP DateTime)

 /*
   * first set timezone as GMT.
   * This is MUST because default timezone is differ from user timezone  
  */     
    $gmt = new DateTimeZone('GMT');
    $user_tz = 'America/Denver';
    $st = new DateTime($row[`start_date`], $gmt);
    // now set user timezone
    $st->setTimezone($user_tz );
    $stime = $qt->format('r');
    echo $stime;

second method (using MySQL UNIX_TIMESTAMP)

#$retrieve data from server in timestamp
$qry = "SELECT `start_date`,UNIX_TIMESTAMP(`start_date`) AS sTimestamp FROM..."  
$st = new DateTime('@'.$row['sTimestamp ']);                     
$stime = $st->format('r');
echo $stime;

Note : не меняйтеstart_date  отметить времяstrtotime(), Он вернет другое значение изUNIX_TIMESTAMP()  то есть

 strtotime($row['start_date']) !== $row['sTimestamp']
1

В следующих строках вы в основном говорите, что дата окончания указывается в GMT, тогда как она должна быть в Америке / Денвере:

$to = new DateTime($end, new DateTimeZone('GMT'));

Затем вы намереваетесь перевести это время в Америку / Денвер, но поскольку вы создали дату, используя часовой пояс GMT, это было бы неправильно в любом случае.

// $to ->setTimeZone($owner_tz);

Это создаст дату окончания, используя часовой пояс пользователя, который, вероятно, то, что вы ищете:

$to = new DateTime($end, $owner_tz);
нет разницы, оба эквивалентны. вы можете проверить.new DateTime($end, $owner_tz); === new DateTime($end,new DateTimeZone('GMT')->setTimeZone($owner_tz); diEcho
Как насчетcodepad.viper-7.com/lrRQPt ?
Как я уже сказал, вы намерены это сделать, но первая строка - то, где вы допустили ошибку. позвольте мне немного перефразировать ответ.
Нет! Я прокомментировал эту строку. я не хочу его менять, потому что время окончания уже сохранено в соответствии с часовым поясом пользователя на момент добавления аукциона. diEcho

Похожие вопросы