Implement more precise timezone handling in edge cases

This commit is contained in:
Kijin Sung 2016-02-11 21:27:36 +09:00
parent b7f04d03bf
commit aaa3e25ad5
3 changed files with 21 additions and 2 deletions

View file

@ -125,6 +125,12 @@ class DateTime
/**
* Get a PHP time zone by UTC offset.
*
* Time zones with both (a) fractional offsets and (b) daylight saving time
* (such as Iran's +03:30/+04:30) cannot be converted in this way.
* However, if Rhymix is installed for the first time in such a time zone,
* the internal time zone will be automatically set to UTC,
* so this should never be a problem in practice.
*
* @param int $offset
* @return bool
*/
@ -133,6 +139,15 @@ class DateTime
switch ($offset)
{
case 0: return 'Etc/UTC';
case -34200: return 'Pacific/Marquesas'; // -09:30
case -16200: return 'America/Caracas'; // -04:30
case 16200: return 'Asia/Kabul'; // +04:30
case 19800: return 'Asia/Kolkata'; // +05:30
case 20700: return 'Asia/Kathmandu'; // +05:45
case 23400: return 'Asia/Rangoon'; // +06:30
case 30600: return 'Asia/Pyongyang'; // +08:30
case 31500: return 'Australia/Eucla'; // +08:45
case 34200: return 'Australia/Darwin'; // +09:30
default: return 'Etc/GMT' . ($offset > 0 ? '-' : '+') . intval(abs($offset / 3600));
}
}

View file

@ -530,8 +530,9 @@ function ztime($str)
{
$hour = $min = $sec = 0;
}
$offset = Rhymix\Framework\Config::get('locale.internal_timezone') ?: date('Z');
return gmmktime($hour, $min, $sec, $month, $day, $year) - $offset;
$timestamp = gmmktime($hour, $min, $sec, $month, $day, $year);
$offset = Rhymix\Framework\Config::get('locale.internal_timezone') ?: date('Z', $timestamp);
return $timestamp - $offset;
}
/**

View file

@ -131,5 +131,8 @@ class DateTimeTest extends \Codeception\TestCase\Test
{
$this->assertEquals('Etc/GMT-9', Rhymix\Framework\DateTime::getTimezoneNameByOffset(32400));
$this->assertEquals('Etc/GMT+5', Rhymix\Framework\DateTime::getTimezoneNameByOffset(-18000));
$this->assertEquals('Etc/UTC', Rhymix\Framework\DateTime::getTimezoneNameByOffset(0));
$this->assertEquals('Asia/Kolkata', Rhymix\Framework\DateTime::getTimezoneNameByOffset(19800));
$this->assertEquals('Australia/Eucla', Rhymix\Framework\DateTime::getTimezoneNameByOffset(31500));
}
}