Даты.. даты.. врменные промежутки, вычисления... факиншит...опять них не работает! а я так надеялся, что появится нормальный класс DateTime который сможет решить мои проблемы.. Впервые глобально озаботился проблемой еще
тут . Но решить ее оказалось лень - каку написал и забил. А вот теперь другой проект, тут надо по-любому решать!
Вообщем устанавливаем врменную зону Europe/Mosсow , вспоминаем когда был переход на зимнее время в прошлом году 25.10.2009 в 03:00 сделали 02:00 . И начинаем испытывать класс DateTime .
<?php
/**
* @author alexob
*/
require_once 'PHPUnit/Framework.php';
class PHPComplianceTest extends PHPUnit_Framework_TestCase{
public function testVersion(){
$this->assertTrue(defined('PHP_VERSION_ID'));
$this->assertTrue(PHP_VERSION_ID >= 50300);
}
public function testDateTimeClass(){
date_default_timezone_set('Europe/Moscow');
$dt = new DateTime('2009-10-25 03:00:00+03');
$this->assertTrue(
(new DateTime('2009-10-25 02:00:00+04')) //говорит баго: '2009-10-25 01:00:00+03'
==
$dt->sub(new DateInterval("PT2H"))
);
$dt = new DateTime('2009-10-25 03:00:00+03');
$this->assertTrue(
(new DateTime('2009-10-25 02:00:00+04')) //говорит баго: '2009-10-25 01:00:00+03'
==
$dt->modify("-2 hours")
);
$dx = new DateTime('2009-10-25 03:00:00+03');
$dt = DateTime::createFromFormat('U', $dx->format('U'));
$dt->sub(new DateInterval("PT2H"));
$dt->setTimezone(new DateTimeZone('Europe/Moscow'));
$this->assertTrue( (new DateTime('2009-10-25 02:00:00+04')) == $dt); //на удивление, правильно
$dt = new DateTime('2009-10-25 01:00:00+04');
$this->assertTrue( (new DateTime('2009-10-25 02:00:00+03')) == $dt->add(new DateInterval("PT2H"))); //верно
$dt = new DateTime('2009-10-25 01:00:00+04');
$this->assertTrue( (new DateTime('2009-10-25 02:00:00+03')) == $dt->modify("+2 hours")); //верно
}
}
Дальше уже тесты писать стало бессмыслено - оно на половину рабочее (только "вперед").
Все проблемы вертятся вокруг DST. Многим оно (DST) до одного места, у многих вообще одна временная зона (или они о том не задумываются/не знают) и они вполне юзают обычные unix timestamp (чаще даже не UTC, а локальное время) и с чистой совестью для получения след. дня делают += 24 * 3600 .
Особо ушлые (
на гуглил такой маневр :) ), поступают вообще интересно :) :
<?php
$ONE_DAY = 90000; // can't use 86400 because some days have one hour more or less
for ( $each_timestamp = $start_time ; $each_timestamp <= $end_time ; $each_timestamp += $ONE_DAY) {
/* force midnight to compensate for daylight saving time */
$this_timestamp_array = getdate( $each_timestamp );
$each_timestamp = mktime ( 0 , 0 , 0 , $this_timestamp_array[mon] , $this_timestamp_array[mday] , $this_timestamp_array[year] );
// do some stuff...
}
?>
Вообще-то функция mktime() может выполнять временнУю арифметику в рамках желаний большинства.. но не моих.
Когда я не смог в течении нескольких часов получить метку времени "полночь" в сутках в которых происходит смена на летне/зимнее время - я забил на DateTime() и успокоился. Переписал этот unit-test наоборот, подставив "ошибки" вместо верных ответов и буду ждать.. рано или поздно это будет исправлено, вот тогда сей тест и завалится, значит пора будет убирать "костыли" и юзать сей мега класс DateTime :(
А в качестве костылей пока использую функции которые все вычисляют с помощью pgsql - там все как в аптеке.
Мож я туплю? может у меня ошибки? хде?