zdate() 함수 튜닝

PHP 5.2 이상 버전에서 사용 가능한 DateTime 클래스를 이용하여 zdate() 함수를 튜닝하였습니다.

아래는 벤치마킹 코드입니다.

테스트를 위해 Context 클래스를 임의로 생성하였기 때문에, 실제 성능과 차이가 있을 수 있습니다.

<code>
<?php
class Context
{
	public static function getLangType()
	{
		return 'ko';
	}

	public static function getLang($lang)
	{
		switch($lang)
		{
			case 'unit_week':
				return array(
					'Monday' => '월',
					'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 '<br>';

$startTime = microtime(TRUE);
for($i=0;$i<100000;$i++)
{
zdate2('20091229');
}
$endTime = microtime(TRUE);
echo floor(($endTime-$startTime) * 1000);
?>
</code>

각각 100000번씩 다섯 차례 반복하여 얻은 테스트 결과입니다. 단위는 ms 입니다.

기존 : 1855
개선 : 1658

기존 : 1843
개선 : 1608

기존 : 1851
개선 : 1624

기존 : 1855
개선 : 1626

기존 : 1826
개선 : 1607