[PHP Class] 양력/음력 변환 PHP 클래스
이전에 구글링을 통하여 얻은 자료이다.
출처는 코드 하단에 있음
양력/음력 변환검증을 위한 참고 사이트
천문우주지석정보(KASI): http://astro.kasi.re.kr/Life/ConvertMonthlyForm.aspx?MenuID=111
아래 소스는 원본사이트이 클래스 소스에서 출력을 위한 테스트 부분만 변경하여 적용한 것임
<?php
class LunarCalendar
{
var $lunarMonthType = array();
// var $accumulateLunarDate = array();
var $SolarToLunar = array();
var $LunarToSolar = array();
var $error = "";
var $solar_start = "1881-01-30";
var $lunar_start = '18810101';
function __construct()
{
// 음력 달력의 달형태를 저장한다.
// 각 해는 13월로 표현되고, 1 작은달, 2 큰달, 3 작은 윤달, 4 큰 윤달 이다. 0 은 윤달이 없는 해에 자리를 채우는 것이다.
// 1881년 1월 30일은 음력 1881년 1월 1일 임으로 이를 기준으로 계산한다.
$monthTypeMark = "1212122322121" . "1212121221220" . "1121121222120" . "2112132122122" . "2112112121220" . "2121211212120" . "2212321121212" . "2122121121210" . "2122121212120"
. "1232122121212" . "1212121221220" . "1121123221222" . "1121121212220" . "1212112121220" . "2121231212121" . "2221211212120" . "1221212121210" . "2123221212121" . "2121212212120"
. "1211212232212" . "1211212122210" . "2121121212220" . "1212132112212" . "2212112112210" . "2212211212120" . "1221412121212" . "1212122121210" . "2112212122120" . "1231212122212"
. "1211212122210" . "2121123122122" . "2121121122120" . "2212112112120" . "2212231212112" . "2122121212120" . "1212122121210" . "2132122122121" . "2112121222120" . "1211212322122"
. "1211211221220" . "2121121121220" . "2122132112122" . "1221212121120" . "2121221212110" . "2122321221212" . "1121212212210" . "2112121221220" . "1231211221222" . "1211211212220"
. "1221123121221" . "2221121121210" . "2221212112120" . "1221241212112" . "1212212212120" . "1121212212210" . "2114121212221" . "2112112122210" . "2211211412212" . "2211211212120"
. "2212121121210" . "2212214112121" . "2122122121120" . "1212122122120" . "1121412122122" . "1121121222120" . "2112112122120" . "2231211212122" . "2121211212120" . "2212121321212"
. "2122121121210" . "2122121212120" . "1212142121212" . "1211221221220" . "1121121221220" . "2114112121222" . "1212112121220" . "2121211232122" . "1221211212120" . "1221212121210"
. "2121223212121" . "2121212212120" . "1211212212210" . "2121321212221" . "2121121212220" . "1212112112210" . "2223211211221" . "2212211212120" . "1221212321212" . "1212122121210"
. "2112212122120" . "1211232122212" . "1211212122210" . "2121121122210" . "2212312112212" . "2212112112120" . "2212121232112" . "2122121212110" . "2212122121210" . "2112124122121"
. "2112121221220" . "1211211221220" . "2121321122122" . "2121121121220" . "2122112112322" . "1221212112120" . "1221221212110" . "2122123221212" . "1121212212210" . "2112121221220"
. "1211231212222" . "1211211212220" . "1221121121220" . "1223212112121" . "2221212112120" . "1221221232112" . "1212212122120" . "1121212212210" . "2112132212221" . "2112112122210"
. "2211211212210" . "2221321121212" . "2212121121210" . "2212212112120" . "1232212122112" . "1212122122120" . "1121212322122" . "1121121222120" . "2112112122120" . "2211231212122"
. "2121211212120" . "2122121121210" . "2124212112121" . "2122121212120" . "1212121223212" . "1211212221220" . "1121121221220" . "2112132121222" . "1212112121220" . "2121211212120"
. "2122321121212" . "1221212121210" . "2121221212120" . "1232121221212" . "1211212212210" . "2121123212221" . "2121121212220" . "1212112112220" . "1221231211221" . "2212211211220"
. "1212212121210" . "2123212212121" . "2112122122120" . "1211212322212" . "1211212122210" . "2121121122120" . "2212114112122" . "2212112112120" . "2212121211210" . "2212232121211"
. "2122122121210" . "2112122122120" . "1231212122212" . "1211211221220" . "2121121321222" . "2121121121220" . "2122112112120" . "2122141211212" . "1221221212110" . "2121221221210"
. "2114121221221";
// $monthTypeMark = "1212122322121" . "1212121221220"; // 디버깅용 데이터.
// $monthTypeMark 에 대응하는 날의수
$dateCount = array(
0,
29,
30,
29,
30
);
//문자열 입력을 배열로 컷팅.
$perYear = str_split($monthTypeMark, 13);
foreach ($perYear as $yearData)
{
$arr = str_split($yearData);
$lunarMonthType[] = $arr;
}
//인덱스 구축.
$solarDate = new DateTime($this->solar_start);
$lastSol = $solarDate->format('Ymd');
$lastLuna = $this->lunar_start;
$lunarYear = (int) substr($this->lunar_start, 0, 4);
foreach ($lunarMonthType as $yearArr)
{
$accArr = array();
$lunarMonth = 0;
foreach ($yearArr as $monthType)
{
if ($monthType == '0')
continue;
$dcnt = $dateCount[$monthType];
$isLeapMonth = false;
if ($monthType == '3' || $monthType == '4')
$isLeapMonth = true;
else
$lunarMonth++;
$lunarYMD = sprintf('%d%02d%02d%s', $lunarYear, $lunarMonth, 1, $isLeapMonth ? 'L' : ' ');
if (isset($this->SolarToLunar[$solarDate->format('Ym')]) == false)
{
$this->SolarToLunar[$solarDate->format('Ym')][$lastSol] = $lastLuna;
}
$this->SolarToLunar[$solarDate->format('Ym')][$solarDate->format('Ymd')] = $lunarYMD;
$this->LunarToSolar[$lunarYMD] = $solarDate->format('Ymd');
$lastSol = $solarDate->format('Ymd');
$lastLuna = $lunarYMD;
$solarDate->add(new DateInterval('P' . $dcnt . 'D'));
}
$lunarYear++;
}
}
/**
* 디버깅용 인덱스 출력함수
*
*/
function print_index()
{
// foreach ($this->SolarToLunar as $k=> $l)
// {
// if(count($l) >1)
// {
// print_r("$k => ");
// print_r($l);
// }
// }
print_r($this->SolarToLunar);
}
/**
* getLunarDate의 반환값을 포맷팅 하기 위한 함수
* 아래 포맷을 지원함
* *Y-m-d : 2010-02-03 형태
* *YmdL : 20100203L 형태, L이 붙으면 윤달 그렇지 않으면 윤달 아님.
* @param unknown_type $lunarDate
* @param unknown_type $fmt
*/
static function formatLunar($lunar, $fmt = 'Y-m-d')
{
$lunarYear = $lunar['year'];
$lunarMonth = $lunar['month'];
$lunarDate = $lunar['date'];
$isLeapMonth = $lunar['is_leap_month'];
return LunarCalendar::formatLunar2($lunarYear, $lunarMonth, $lunarDate, $isLeapMonth, $fmt);
}
/**
* 포맷팅 지원함수.
* @param unknown_type $lunarYear
* @param unknown_type $lunarMonth
* @param unknown_type $lunarDate
* @param unknown_type $isLeapMonth
* @param unknown_type $fmt
*/
static function formatLunar2($lunarYear, $lunarMonth, $lunarDate, $isLeapMonth, $fmt)
{
switch ($fmt)
{
case 'Y-m-d':
$lunarYMD = sprintf('%04d-%02d-%02d', $lunarYear, $lunarMonth, $lunarDate);
break;
case 'YmdL':
$lunarYMD = sprintf('%04d%02d%02d%s', $lunarYear, $lunarMonth, $lunarDate, $isLeapMonth ? 'L' : ' ');
break;
}
return $lunarYMD;
}
/**
* getLunarDate의 쓰기 편한 형태
* 2010-03-18 형태로 아규먼트를 넣을수 있음.
*
* @param unknown_type $Y_m_d
*/
function getLunarDateYmd($Y_m_d)
{
// print_r('$Y_m_d' .$Y_m_d);
$format = "Y-m-d";
$tm = date_parse_from_format($format, $Y_m_d);
$year = $tm["year"];
$month = $tm["month"];
$date = $tm["day"];
// print_r($tm);
return $this->getLunarDate($year, $month, $date);
}
/**
*
* 음력으로 돌려줌.
* 반환은 아래 형태
Array
(
[year] => 2050
[month] => 03
[date] => 9
[is_leap_month] => 0 // 윤달 여부, 1이면 윤달.
)
* 계산 범위 초과시 null
* @param unknown_type $year
* @param unknown_type $month
* @param unknown_type $date
*/
function getLunarDate($year, $month, $date)
{
$this->error = "";
list($nearSol, $nearLuna) = $this->_getNearData($year, $month, $date);
if (empty($nearSol))
return null;
//키와 입력과의 날짜 차이만금, lunarPinDate에 더한다.
$targetJD = cal_to_jd(CAL_GREGORIAN, $month, $date, $year);
$keyJD = cal_to_jd(CAL_GREGORIAN, substr($nearSol, 4, 2), substr($nearSol, 6, 2), substr($nearSol, 0, 4));
$diff = $targetJD - $keyJD;
$lunarYear = substr($nearLuna, 0, 4);
$lunarMonth = substr($nearLuna, 4, 2);
$lunarDate = substr($nearLuna, 6, 2);
$lunarLeapMonth = substr($nearLuna, 8, 1);
$lunarDate += $diff;
return array(
'year' => $lunarYear,
'month' => $lunarMonth,
'date' => $lunarDate,
'is_leap_month' => $lunarLeapMonth == 'L' ? 1 : 0,
);
}
function _getNearData($year, $month, $date)
{
$ym = sprintf('%d%02d', $year, $month);
$ymd = sprintf('%d%02d%02d', $year, $month, $date);
if (false == isset($this->SolarToLunar[$ym]))
{
$this->error = '계산할수 있는 범위가 아닙니다.';
return null;
}
$pair = $this->SolarToLunar[$ym];
$lastLuna = '';
$lastSol = "";
// print_r($pair);
foreach ($pair as $sol => $luna)
{
// print_r('$ymd < $keys[$i] ' . "$ymd < $keys[$i]\n");
// print_r("$ymd $sol $luna");
if ($ymd < $sol)
{
return array(
$lastSol,
$lastLuna
);
}
else if ($ymd == $sol)
{
return array(
$sol,
$luna
);
}
$lastSol = $sol;
$lastLuna = $luna;
}
return array(
$lastSol,
$lastLuna
);
}
/**
* 음력에 대응하는 양력 날짜 구하기.
* @param unknown_type $lunarYear
* @param unknown_type $lunarMonth
* @param unknown_type $lunarDate
* @param unknown_type $isLeapMonth
*/
function getSolarDate($lunarYear, $lunarMonth, $lunarDate, $isLeapMonth = false)
{
$this->error = "";
$nearKey = sprintf('%d%02d%02d%s', $lunarYear, $lunarMonth, 1, $isLeapMonth ? 'L' : ' ');
if (false == isset($this->LunarToSolar[$nearKey]))
{
$this->error = '계산할수 있는 범위가 아닙니다.';
return null;
}
$solarPinDate = $this->LunarToSolar[$nearKey];
//키와 입력과의 날짜 차이만금, $solarPinDate 더한다.
$keyDate = substr($nearKey, 6, 2);
$keyIsLeapMonth = ('L' == substr($nearKey, 8, 1) ? true : false);
if ($keyIsLeapMonth != $isLeapMonth)
{
$this->error = ($isLeapMonth ? "윤달" : "평달") . "$lunarYear-$lunarMonth-$lunarDate" . '는 없음.';
return null;
}
$diff = $lunarDate - $keyDate;
$date = DateTime::createFromFormat('Ymd', $solarPinDate);
// print_r($date);
$date->add(new DateInterval('P' . $diff . 'D'));
// print_r($date);
return $date->format('Y-m-d');
}
}
/* 테스트 용 소스 */
$Y = 2012;
$D = 04;
$LunarCalendar = new LunarCalendar();
echo "Sol -> Moon Test<br />";
for($i=1;$i<=30;$i++) {
$rst = $LunarCalendar->getLunarDate($Y, $D, $i);
$rst = $LunarCalendar->formatLunar($rst);
echo "{$Y}-{$D}-{$i} -> ".$rst."<br />";
}
echo "<br />";
echo "<br />";
echo "Moon -> Sol Test<br />";
for($i=1;$i<=31;$i++) {
$rst = $LunarCalendar->getSolarDate($Y, $D, $i, false);
echo "{$Y}-{$D}-{$i} -> ".$rst."<br />";
}
?>
코드 원본 출처 사이트: http://vollfeed.createmania.co.kr/wiki/index.php/%EC%9D%8C%EB%A0%A5%EA%B3%84%EC%82%B0 (현재 접속 안됨)
이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스 에 따라 이용할 수 있습니다.
Comments
Related Posts
PHP 정규식 패턴 모음 preg 사용
자주 사용되는 정규식 및 그누보드에서 사용하기 좋은 코드를 모아서 정리 하였다. 자주 업데이트 하지 않겠지만, 그래도 나중에 필요 할 때 찾아서 볼 수 있었으면 좋겠다. 사…
그누보드4 아이디 변경 함수 - 모든 테이블의 아이디를 변경
그누보드 사용시 아이디값을 이메일등으로 사용하거나 아이디를 변경하게 하도록 하는 사이트들이 존재 한다. 그누보드에서는 아이디 값이 게시판테이블에서나 포인트등 에서 회원을 구분하…
GD를 이용한 기본기능 썸네일,CROP,CROP썸네일,텍스트 만들기에 기능추가
GD Library를 이용한 Thumbnail 생성 클래스입니다. 기본적인 이미지 리사이징 및 리사이징과 동시에 비율에 맞춰 Crop 하는 기능이 있고, 워터마크를 추가 할 수…