2011-08-24 3 views
3

a bug in Zend_Date when setting a time that crosses the DST change을 발견했습니다.Zend 날짜 DST 버그에 대한 해결 방법

date_default_timezone_set('America/New_York'); 

echo '<pre>'; 

// DST BEGINS '2012-03-11 02:00:00' - "Spring Forward" 
$a = new Zend_Date('2012-03-11 00:00:00', 'yyyy-MM-dd HH:mm:ss'); 
$a->setTime('04:00:00', 'HH:mm:ss'); 
echo $a->toString('yyyy-MM-dd HH:mm:ss', 'iso') 
     . ' // expected: 2012-03-11 04:00:00' . PHP_EOL; 
$b = new Zend_Date('2012-03-11 04:00:00', 'yyyy-MM-dd HH:mm:ss'); 
$b->setTime('00:00:00', 'HH:mm:ss'); 
echo $b->toString('yyyy-MM-dd HH:mm:ss', 'iso') 
     . ' // expected: 2012-03-11 00:00:00' . PHP_EOL; 

// DST ENDS '2012-11-04 02:00:00' - "Fall Back" 
$c = new Zend_Date('2012-11-04 00:00:00', 'yyyy-MM-dd HH:mm:ss'); 
$c->setTime('04:00:00', 'HH:mm:ss'); 
echo $c->toString('yyyy-MM-dd HH:mm:ss', 'iso') 
     . ' // expected: 2012-11-06 04:00:00' . PHP_EOL; 
$d = new Zend_Date('2012-11-04 04:00:00', 'yyyy-MM-dd HH:mm:ss'); 
$d->setTime('00:00:00', 'HH:mm:ss'); 
echo $d->toString('yyyy-MM-dd HH:mm:ss', 'iso') 
     . ' // expected: 2012-11-06 00:00:00' . PHP_EOL; 

echo '</pre>'; 

으로 출력한다 :

여기에 문제를 보여 코드의

2012-03-11 05:00:00 // expected: 2012-03-11 04:00:00 
2012-03-10 23:00:00 // expected: 2012-03-11 00:00:00 
2012-11-04 03:00:00 // expected: 2012-11-06 04:00:00 
2012-11-04 01:00:00 // expected: 2012-11-06 00:00:00 

나는이 버그를 해결해야하고, 내가 난처한 상황에 빠진입니다.


솔루션

nerdzila에서 the answer을 바탕으로, 연구 a bug introduced by his solution에, 지금이가 내 하위 분류 Zend_Date :

/** 
* Call the function twice to work around the DST bug 
* http://zendframework.com/issues/browse/ZF-10584 
* https://stackoverflow.com/questions/7181702/work-around-for-zend-date-dst-bug 
* https://stackoverflow.com/questions/8593660/zend-date-dst-bug-test-whether-a-date-is-a-time-change-date 
* TODO: remove this once the bug is fixed 
* 
* @param string|integer|array|Zend_Date $time Time to set 
* @param string       $format OPTIONAL Timeformat for parsing input 
* @param string|Zend_Locale    $locale OPTIONAL Locale for parsing input 
* @return My_Date Provides fluid interface 
* @throws Zend_Date_Exception 
*/ 
public function setTime($time, $format = null, $locale = null) 
{ 
    // start time zone juggling so that localtime() returns the correct results 
    $tzOrig = date_default_timezone_get(); 
    date_default_timezone_set($this->getTimezone()); 

    // capture orignal info 
    $timeInfoOrg = localtime($this->getTimestamp(), true); 

    // set the time 
    parent::setTime($time, $format, $locale); 

    // if the dst has changed, perform workaround 
    $timeInfoNew = localtime($this->getTimestamp(), true); 
    if ((0 < $timeInfoOrg['tm_isdst']) != (0 < $timeInfoNew['tm_isdst'])) { 
     // set the time again 
     parent::setTime($time, $format, $locale); 
     // if the day changed, set it back 
     if ($timeInfoOrg['tm_yday'] != $timeInfoNew['tm_yday']) { 
      // localtime() year date is zero indexed, add one 
      $this->setDayOfYear($timeInfoOrg['tm_yday'] + 1); 
     } 
    } 

    // end time zone juggling 
    date_default_timezone_set($tzOrig); 

    // fluent 
    return $this; 
} 

나는 단순히 한 번 제거 할 수 있습니다 버그가 수정되었습니다.

답변

4

이것은 불행한 버그입니다. 나는 각 날짜에 대해 두 번 setTime()를 호출하여 주위를 가지고 :

... 
$a->setTime('04:00:00', 'HH:mm:ss'); 
$a->setTime('04:00:00', 'HH:mm:ss'); 
... 
$b->setTime('00:00:00', 'HH:mm:ss'); 
$b->setTime('00:00:00', 'HH:mm:ss'); 
... 
$c->setTime('04:00:00', 'HH:mm:ss'); 
$c->setTime('04:00:00', 'HH:mm:ss'); 
... 
$d->setTime('00:00:00', 'HH:mm:ss'); 
$d->setTime('00:00:00', 'HH:mm:ss'); 
... 

내 결과 :

2012-03-11 04:00:00 // expected: 2012-03-11 04:00:00 
2012-03-10 00:00:00 // expected: 2012-03-11 00:00:00 
2012-11-04 04:00:00 // expected: 2012-11-04 04:00:00 
2012-11-04 00:00:00 // expected: 2012-11-04 00:00:00 
+0

감사합니다! 상관 없으면 문제 추적기에 계정을 만들고 버그를 upvote하십시오. 어쩌면 그것이 더 높은 우선 순위를 줄 것입니다. – Sonny

+0

http://zendframework.com/issues/browse/ZF-10584 – Sonny

+2

OK, 투표했습니다. 해결해야합니다. – nerdzila

관련 문제