Merge pull request #263 from kijin/pr/extra-timezones

표준 시간대 처리 개선 추가
This commit is contained in:
Kijin Sung 2016-02-12 09:48:46 +09:00
commit bd11d8b152
5 changed files with 106 additions and 15 deletions

View file

@ -126,14 +126,15 @@ class DefaultValue
switch($func_name)
{
case 'ipaddress' :
$val = '$_SERVER[\'REMOTE_ADDR\']';
$val = '\\RX_CLIENT_IP';
$this->_is_string_from_function = TRUE;
break;
case 'unixtime' :
$val = '$_SERVER[\'REQUEST_TIME\']';
$val = '\\RX_TIME';
$this->_is_string_from_function = TRUE;
break;
case 'curdate' :
$val = 'date("YmdHis")';
$val = 'getInternalDateTime()';
$this->_is_string_from_function = TRUE;
break;
case 'sequence' :

View file

@ -12,6 +12,19 @@ class DateTime
*/
protected static $_timezones = array();
/**
* Format a Unix timestamp using the internal timezone.
*
* @param string $format Format used in PHP date() function
* @param int $timestamp Unix timestamp (optional, default is now)
* @return string
*/
public static function formatTimestamp($format, $timestamp = null)
{
$offset = Config::get('locale.internal_timezone') ?: date('Z', $timestamp);
return gmdate($format, $timestamp + $offset);
}
/**
* Format a Unix timestamp for the current user's timezone.
*
@ -125,6 +138,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 +152,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

@ -195,10 +195,10 @@ $lang->unit_meridiem['am'] = '오전';
$lang->unit_meridiem['pm'] = '오후';
$lang->unit_meridiem['AM'] = '오전';
$lang->unit_meridiem['PM'] = '오후';
$lang->time_gap['min'] = '%d 분 전';
$lang->time_gap['mins'] = '%d 분 전';
$lang->time_gap['hour'] = '%d 시간 전';
$lang->time_gap['hours'] = '%d 시간 전';
$lang->time_gap['min'] = '%d분 전';
$lang->time_gap['mins'] = '%d분 전';
$lang->time_gap['hour'] = '%d시간 전';
$lang->time_gap['hours'] = '%d시간 전';
$lang->about_tag = '쉼표(,)를 이용하여 복수 등록';
$lang->about_layout = '레이아웃은 콘텐츠의 겉모습을 꾸며줍니다. 상단 레이아웃 메뉴에서 관리할 수 있습니다.';
$lang->about_ipaddress_input = 'IP주소 입력형식<br />1. 와일드카드(*) 사용가능(예: 192.168.0.*)<br />2. 하이픈(-)을 사용하여 대역으로 입력가능<br />(단, 대역폭으로 입력할 경우 와일드카드 사용불가. 예: 192.168.0.1-192.168.0.254)<br />3.여러개의 항목은 줄을 바꾸어 입력하세요';

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;
}
/**
@ -601,6 +602,32 @@ function zdate($str, $format = 'Y-m-d H:i:s', $conversion = false)
return $result;
}
/**
* Convert a Unix timestamp to YYYYMMDDHHIISS format, using the internal time zone.
* If the timestamp is not given, the current time is used.
*
* @param int $timestamp Unix timestamp
* @return string
*/
function getInternalDateTime($timestamp = null, $format = 'YmdHis')
{
$timestamp = ($timestamp !== null) ? $timestamp : time();
return Rhymix\Framework\DateTime::formatTimestamp($format, $timestamp);
}
/**
* Convert a Unix timestamp to YYYYMMDDHHIISS format, using the internal time zone.
* If the timestamp is not given, the current time is used.
*
* @param int $timestamp Unix timestamp
* @return string
*/
function getDisplayDateTime($timestamp = null, $format = 'YmdHis')
{
$timestamp = ($timestamp !== null) ? $timestamp : time();
return Rhymix\Framework\DateTime::formatTimestampForCurrentUser($format, $timestamp);
}
/**
* If the recent post within a day, output format of YmdHis is "min/hours ago from now". If not within a day, it return format string.
*
@ -613,21 +640,21 @@ function getTimeGap($date, $format = 'Y.m.d')
$gap = RX_TIME - ztime($date);
$lang_time_gap = Context::getLang('time_gap');
if($gap < 60)
if($gap < 60 * 1.5)
{
$buff = sprintf($lang_time_gap['min'], (int)($gap / 60) + 1);
$buff = sprintf($lang_time_gap['min'], round($gap / 60));
}
elseif($gap < 60 * 60)
{
$buff = sprintf($lang_time_gap['mins'], (int)($gap / 60) + 1);
$buff = sprintf($lang_time_gap['mins'], round($gap / 60));
}
elseif($gap < 60 * 60 * 2)
elseif($gap < 60 * 60 * 1.5)
{
$buff = sprintf($lang_time_gap['hour'], (int)($gap / 60 / 60) + 1);
$buff = sprintf($lang_time_gap['hour'], round($gap / 60 / 60));
}
elseif($gap < 60 * 60 * 24)
{
$buff = sprintf($lang_time_gap['hours'], (int)($gap / 60 / 60) + 1);
$buff = sprintf($lang_time_gap['hours'], round($gap / 60 / 60));
}
else
{

View file

@ -62,6 +62,35 @@ class DateTimeTest extends \Codeception\TestCase\Test
Rhymix\Framework\Config::set('locale.internal_timezone', 10800);
}
public function testGetInternalDateTime()
{
$timestamp = 1454000000;
// Test zdate() when the internal time zone is different from the default time zone.
Rhymix\Framework\Config::set('locale.internal_timezone', 10800);
$this->assertEquals('20160128195320', getInternalDateTime($timestamp));
// Test zdate() when the internal time zone is the same as the default time zone.
Rhymix\Framework\Config::set('locale.internal_timezone', 32400);
$this->assertEquals('20160129015320', getInternalDateTime($timestamp));
}
public function testGetTimeGap()
{
Context::getInstance()->lang = Rhymix\Framework\Lang::getInstance('en');
Context::getInstance()->lang->loadPlugin('common');
// Test getTimeGap() when the internal time zone is different from the default time zone.
Rhymix\Framework\Config::set('locale.internal_timezone', 10800);
$this->assertEquals('30 minutes ago', getTimeGap(getInternalDateTime(RX_TIME - 1800)));
$this->assertEquals('2 hours ago', getTimeGap(getInternalDateTime(RX_TIME - 6000)));
// Test getTimeGap() when the internal time zone is the same as the default time zone.
Rhymix\Framework\Config::set('locale.internal_timezone', 32400);
$this->assertEquals('30 minutes ago', getTimeGap(getInternalDateTime(RX_TIME - 1800)));
$this->assertEquals('2 hours ago', getTimeGap(getInternalDateTime(RX_TIME - 6000)));
}
public function testGetTimezoneForCurrentUser()
{
// Test when the current user's time zone is different from the system default.
@ -82,16 +111,19 @@ class DateTimeTest extends \Codeception\TestCase\Test
$_SESSION['timezone'] = 'America/Chicago';
$this->assertEquals('20160128 105320', Rhymix\Framework\DateTime::formatTimestampForCurrentUser('Ymd His', $timestamp_winter));
$this->assertEquals('20150728 115320', Rhymix\Framework\DateTime::formatTimestampForCurrentUser('Ymd His', $timestamp_summer));
$this->assertEquals('20150728 115320', getDisplayDateTime($timestamp_summer, 'Ymd His'));
// Test when the current user's time zone is in the Southern hemisphere with DST.
$_SESSION['timezone'] = 'Pacific/Auckland';
$this->assertEquals('20160129 055320', Rhymix\Framework\DateTime::formatTimestampForCurrentUser('Ymd His', $timestamp_winter));
$this->assertEquals('20150729 045320', Rhymix\Framework\DateTime::formatTimestampForCurrentUser('Ymd His', $timestamp_summer));
$this->assertEquals('20150729 045320', getDisplayDateTime($timestamp_summer, 'Ymd His'));
// Test when the current user's time zone is the same as the system default without DST.
unset($_SESSION['timezone']);
$this->assertEquals('20160129 015320', Rhymix\Framework\DateTime::formatTimestampForCurrentUser('Ymd His', $timestamp_winter));
$this->assertEquals('20150729 015320', Rhymix\Framework\DateTime::formatTimestampForCurrentUser('Ymd His', $timestamp_summer));
$this->assertEquals('20150729 015320', getDisplayDateTime($timestamp_summer, 'Ymd His'));
}
public function testGetTimezoneList()
@ -131,5 +163,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));
}
}