xpressengine/xe-core — pull request #830 by smaker (2014-07-08 02:36:22+00:00)
Title: zdate() 함수 튜닝

PHP 5.2 이상 버전에서 사용 가능한 DateTime 클래스를 이용하여 zdate() 함수를 튜닝하였습니다.

아래는 벤치마킹 코드입니다.

테스트를 위해 Context 클래스를 임의로 생성하였기 때문에, 실제 성능과 차이가 있을 수 있습니다.

'월',
'Tuesday' => '화',
'Wednesday' => '수',
'Thursday' => '목',
'Friday' => '금',
'Saturday' => '토',
'Sunday' => '일'
);
break;
case 'unit_meridiem':
return array(
'am' => '오전',
'pm' => '오후',
'AM' => '오전',
'PM' => '오후'
);

break;
}
}
}

$GLOBALS['_time_zone'] = date('O');

/**
* Get a time gap between server's timezone and XE's timezone
*
* @return int
*/
function zgap()
{
$time_zone = $GLOBALS['_time_zone'];
if($time_zone < 0)
{
$to = -1;
}
else
{
$to = 1;
}

$t_hour = substr($time_zone, 1, 2) * $to;
$t_min = substr($time_zone, 3, 2) * $to;

$server_time_zone = date("O");
if($server_time_zone < 0)
{
$so = -1;
}
else
{
$so = 1;
}

$c_hour = substr($server_time_zone, 1, 2) * $so;
$c_min = substr($server_time_zone, 3, 2) * $so;

$g_min = $t_min - $c_min;
$g_hour = $t_hour - $c_hour;

$gap = $g_min * 60 + $g_hour * 60 * 60;
return $gap;
}

/**
* YYYYMMDDHHIISS format changed to unix time value
*
* @param string $str Time value in format of YYYYMMDDHHIISS
* @return int
*/
function ztime($str)
{
if(!$str)
{
return;
}

$hour = (int) substr($str, 8, 2);
$min = (int) substr($str, 10, 2);
$sec = (int) substr($str, 12, 2);
$year = (int) substr($str, 0, 4);
$month = (int) substr($str, 4, 2);
$day = (int) substr($str, 6, 2);
if(strlen($str) <= 8)
{
$gap = 0;
}
else
{
$gap = zgap();
}

return mktime($hour, $min, $sec, $month ? $month : 1, $day ? $day : 1, $year) + $gap;
}

/**
* Change the time format YYYYMMDDHHIISS to the user defined format
*
* @param string|int $str YYYYMMDDHHIISS format time values
* @param string $format Time format of php date() function
* @param bool $conversion Means whether to convert automatically according to the language
* @return string
*/
function zdate($str, $format = 'Y-m-d H:i:s', $conversion = TRUE)
{
// return null if no target time is specified
if(!$str)
{
return;
}
// convert the date format according to the language
if($conversion == TRUE)
{
switch(Context::getLangType())
{
case 'en' :
case 'es' :
if($format == 'Y-m-d')
{
$format = 'M d, Y';
}
elseif($format == 'Y-m-d H:i:s')
{
$format = 'M d, Y H:i:s';
}
elseif($format == 'Y-m-d H:i')
{
$format = 'M d, Y H:i';
}
break;
case 'vi' :
if($format == 'Y-m-d')
{
$format = 'd-m-Y';
}
elseif($format == 'Y-m-d H:i:s')
{
$format = 'H:i:s d-m-Y';
}
elseif($format == 'Y-m-d H:i')
{
$format = 'H:i d-m-Y';
}
break;
}
}

// If year value is less than 1970, handle it separately.
if((int) substr($str, 0, 4) < 1970)
{
$hour = (int) substr($str, 8, 2);
$min = (int) substr($str, 10, 2);
$sec = (int) substr($str, 12, 2);
$year = (int) substr($str, 0, 4);
$month = (int) substr($str, 4, 2);
$day = (int) substr($str, 6, 2);

// leading zero?
$lz = create_function('$n', 'return ($n>9?"":"0").$n;');

$trans = array(
'Y' => $year,
'y' => $lz($year % 100),
'm' => $lz($month),
'n' => $month,
'd' => $lz($day),
'j' => $day,
'G' => $hour,
'H' => $lz($hour),
'g' => $hour % 12,
'h' => $lz($hour % 12),
'i' => $lz($min),
's' => $lz($sec),
'M' => getMonthName($month),
'F' => getMonthName($month, FALSE)
);

$string = strtr($format, $trans);
}
else
{
// if year value is greater than 1970, get unixtime by using ztime() for date() function's argument.
$string = date($format, ztime($str));
}
// change day and am/pm for each language
$unit_week = Context::getLang('unit_week');
$unit_meridiem = Context::getLang('unit_meridiem');
$string = str_replace(array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'), $unit_week, $string);
$string = str_replace(array('am', 'pm', 'AM', 'PM'), $unit_meridiem, $string);
return $string;
}

function zdate2($str, $format = 'Y-m-d H:i:s', $conversion = TRUE)
{
// return null if no target time is specified
if(!$str)
{
return;
}
// convert the date format according to the language
if($conversion == TRUE)
{
switch(Context::getLangType())
{
case 'en' :
case 'es' :
if($format == 'Y-m-d')
{
$format = 'M d, Y';
}
elseif($format == 'Y-m-d H:i:s')
{
$format = 'M d, Y H:i:s';
}
elseif($format == 'Y-m-d H:i')
{
$format = 'M d, Y H:i';
}
break;
case 'vi' :
if($format == 'Y-m-d')
{
$format = 'd-m-Y';
}
elseif($format == 'Y-m-d H:i:s')
{
$format = 'H:i:s d-m-Y';
}
elseif($format == 'Y-m-d H:i')
{
$format = 'H:i d-m-Y';
}
break;
}
}

$date = new DateTime($str);
$string = $date->format($format);

// change day and am/pm for each language
$unit_week = Context::getLang('unit_week');
$unit_meridiem = Context::getLang('unit_meridiem');
$string = str_replace(array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'), $unit_week, $string);
$string = str_replace(array('am', 'pm', 'AM', 'PM'), $unit_meridiem, $string);
return $string;
}

$startTime = microtime(TRUE);
for($i=0;$i<100000;$i++)
{
zdate('20091229');
}
$endTime = microtime(TRUE);
echo floor(($endTime-$startTime) * 1000);
echo '
';

$startTime = microtime(TRUE);
for($i=0;$i<100000;$i++)
{
zdate2('20091229');
}
$endTime = microtime(TRUE);
echo floor(($endTime-$startTime) * 1000);
?>

각각 100000번씩 다섯 차례 반복하여 얻은 테스트 결과입니다. 단위는 ms 입니다.

기존 : 1855
개선 : 1658

기존 : 1843
개선 : 1608

기존 : 1851
개선 : 1624

기존 : 1855
개선 : 1626

기존 : 1826
개선 : 1607