2013. 11. 25.

PHP 양력 날짜를 음력 날짜로 변환해주는 함수.

달력에 보면 조그맣게 음력 날짜가 표시되어 있습니다. 우리나라도 아직까지 음력으로 생일이나 기념일을 하시는 분들이 많이 계시죠. 음력에 대한 지식이 전무했던 지라... 전 그저 양력을 음력으로 변환해 주는 함수가 존재하고 양력 날짜 인수만 갖다 넣으면 음력 날짜가 뿅! 하고 나올 줄만 알았습니다. :-(

제가 원했던 것은 20131125 라는 양력 날짜를 넣으면 20131023 이란 음력 날짜를 반환해주는 함수였을 뿐인데... 이게 간단한 문제가 아닌거 같더군요. 양력을 음력으로 바꾸는데는 간단한 수식으로 해결 할 수가 없다고 합니다. 천체의 운행을 기법으로 하는.... 뭐...

이것저것 함수들을 찾아보니 일정 기간의 음력을 데이터베이스 처럼 입력해 놓고 처리하는 방식이고, 특정 년도 이전까지만 유효하게끔 되어 있습니다. 그 만큼 골치아프고 어려운가 봅니다... 게다가 양/음력 날짜를 변환해주는 웹페이지들도 있던데 변환 시 날짜가 아주 엉망으로 나오는 곳도 한 두 군데가 아니더군요.

습관처럼 구글에서 영어로 검색을 한참동안 했는데, 검색을 하면 할 수록 감이 더 안잡히는 불상사가 발생 합니다. 음력이라기에 lunar date 란 검색어로, 양력은 solar date 검색어로 이리저리 찾아봤습니다만... islamic calendar(이슬람 달력)과 chinese calendar(중국 달력) 이 연관되서 나오기 시작하고, Gregorian 날짜와 Julian 날짜 뭐... 하하... 이슬람력이 중국으로 그리고 우리나라로 온 것 같고...

깊은 절망에 빠져들게 만들었던 검색결과의 링크들 입니다.
현재 시간을 Lunar Standard Time 으로 바꿔 줍니다. 46-09-16은 도무지 무슨 날짠지 모르겠네요...
http://random.kakaopor.hu/lunar-date-function-for-php-time-on-the-moon-lst
http://lunarclock.org/convert-to-lunar-standard-time.php

해당 날짜에 맞는 달의 상태를 계산에 줍니다. 보름달인지 반달인지 그런거요. 밑에 것도...
http://jivebay.com/calculating-the-moon-phase/
http://www.phpclasses.org/package/1201-PHP-Calculates-the-phase-of-the-Moon.html

위에서 말한 Gregorian, Julian 녀석들 자바스크립트 라이브러린듯 합니다.
http://stackoverflow.com/questions/12637268/convert-julian-date-to-solar-date-in-javascript
http://jesusnjim.com/common/julian-gregorian.html#tog


영혼 없는 검색질 중 문득 든 생각이 한국어페이지로 검색 하는게 더 나을꺼 같다는 생각이 들더군요. 한국어 웹페이지를 검색하니, 답이 보이기 시작 합니다. 동일한 소스를 여러곳에서 찾았는데 아무리 봐도 해당 블로그는 소스 출처가 아닌 것 같더군요. 긁어서 붙여넣은 모습이 보여서 해당 소스의 출처는 찾질 못했습니다. 혹시 출처를 아시는 분 계시면 알려 주시면 바로 반영 하도록 하겠습니다.

잡소리가 엄청나게 길었네요. 아래 소스를 적당하게 붙여넣으시고 사용하시면 됩니다. 벽에 걸려있는 달력이랑 비교해보니 잘 맞게 나오더라구요. 만족 합니다. 반환되는 객체의 time 필드가 time() 함수를 호출 했을때 반환 값 형식인 timestamp 인듯 합니다. date() 함수로 포멧을 주고 변환해주면 음력 날짜를 간단하게 얻을 수 있습니다.

<?
function sunlunar_data() {
return
"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";
}

function SolaToLunar($yyyymmdd) {
$getYEAR = substr($yyyymmdd,0,4);
$getMONTH = substr($yyyymmdd,4,2);
$getDAY = substr($yyyymmdd,6,2);

$arrayDATASTR = sunlunar_data();
$arrayDATA = explode("-",$arrayDATASTR);
$arrayLDAYSTR="31-0-31-30-31-30-31-31-30-31-30-31";
$arrayLDAY = explode("-",$arrayLDAYSTR);
$dt = $arrayDATA;



for ($i=0;$i<=168;$i++) {
  $dt[$i] = 0;
  for ($j=0;$j<12;$j++) {
    switch (substr($arrayDATA[$i],$j,1)) {

    case 1:
      $dt[$i] += 29;
      break;

    case 3:
      $dt[$i] += 29;
      break;

    case 2:
      $dt[$i] += 30;
      break;

    case 4:
      $dt[$i] += 30;
      break;
    }
  }

  switch (substr($arrayDATA[$i],12,1)) {

  case 0:
    break;

  case 1:
    $dt[$i] += 29;
    break;

  case 3:
    $dt[$i] += 29;
    break;

  case 2:
    $dt[$i] += 30;
    break;

  case 4:
    $dt[$i] += 30;
    break;
  }
}

$td1 = 1880 * 365 + (int)(1880/4) - (int)(1880/100) + (int)(1880/400) + 30;
$k11 = $getYEAR - 1;
$td2 = $k11 * 365 + (int)($k11/4) - (int)($k11/100) + (int)($k11/400);

if ($getYEAR % 400 == 0 || $getYEAR % 100 != 0 && $getYEAR % 4 == 0) {
  $arrayLDAY[1] = 29;

} else {
  $arrayLDAY[1] = 28;
}

if ($getMONTH > 13) {
  $gf_sol2lun = 0;
}

if ($getDAY > $arrayLDAY[$getMONTH-1]) {
  $gf_sol2lun = 0;
}

for ($i=0;$i<=$getMONTH-2;$i++) {
  $td2 += $arrayLDAY[$i];
}

$td2 += $getDAY;
$td = $td2 - $td1 + 1;
$td0 = $dt[0];

for ($i=0;$i<=168;$i++) {
  if ($td <= $td0) {
    break;
  }
  $td0 += $dt[$i+1];
}

$ryear = $i + 1881;
$td0 -= $dt[$i];
$td -= $td0;

if (substr($arrayDATA[$i], 12, 1) == 0) {
  $jcount = 11;

} else {
  $jcount = 12;
}

$m2 = 0;

for ($j=0;$j<=$jcount;$j++) { // 달수 check, 윤달 > 2 (by harcoon)
  if (substr($arrayDATA[$i],$j,1) <= 2) {
    $m2++;
    $m1 = substr($arrayDATA[$i],$j,1) + 28;
    $gf_yun = 0;
  } else {
    $m1 = substr($arrayDATA[$i],$j,1) + 26;
    $gf_yun = 1;
  }
  if ($td <= $m1) {
    break;
  }
  $td = $td - $m1;
}

$k1=($ryear+6) % 10;
$syuk = $arrayYUK[$k1];
$k2=($ryear+8) % 12;
$sgap = $arrayGAP[$k2];
$sddi = $arrayDDI[$k2];
$gf_sol2lun = 1;

if($m2<10) $m2="0".$m2;
if($sday<10) $td="0".$td;

$Ary[year]=$ryear;
$Ary[month]=$m2;
$Ary[day]=$td;
$Ary[time]=mktime(0,0,0,$Ary[month],$Ary[day],$Ary[year]);

return $Ary;

}

//사용 예
$lunar_date = SolaToLunar($f_date);
echo date("Y-m-d", $lunar_date[time]);
?>

댓글 2개 :