Source for file KASI_Lunar.php
Documentation is available at KASI_Lunar.php
* Project: oops\KASI\Lunar:: 한국천문연구원 데이터를 기반으로 한 음/양력 변환 클래스<br>
* - {@link http://pear.oops.org/docs/li_myException.html oops/myException}
* - {@link http://kr1.php.net/manual/en/book.calendar.php calendar extension}
* 이 패키지는 한국천문연구원의 음양력 데이터를 기반으로 하여 양력/음열간의 변환을
* 제공하며, aero님의 Date-Korean-0.0.2 perl module을 PHP로 포팅한 것이다.
* 양력 기준으로 1391-02-05 부터 2050-12-31 까지의 기간만 가능하며, 절기, 합삭/망
* 정보, 세차/월간/일진등의 정보는 oops\Lunar pear package를 이용하도록 한다.
* 이 패키지는 pear/Lunar package의 확장을 위하여 제작이 되었으며, 라이센스 문제로
* pear/Lunar package와 별도의 패키지로 제작이 되었다.
* @package oops\KASI\Lunar
* @author JoungKyun.Kim <http://oops.org>
* @copyright (c) 2024, OOPS.org
* @license GPL (or Perl license)
* @link https://github.com/OOPS-ORG-PHP/KASI-Lunar
* @since File available since release 0.0.1
* @example KASI-Lunar/tests/test.php Sample code
* import myException class
require_once 'myException.php';
require_once 'KASI_Lunar/Lunar_Tables.php';
require_once 'KASI_Lunar/Lunar_Seasons.php';
* oops\KASI pear package의 main class
* 한국천문연구원 데이터를 기반으로 한 음/양력 변환 클래스
* 이 패키지는 한국천문연구원의 음양력 데이터를 기반으로 하여 양력/음열간의 변환을
* 제공하며, aero님의 Date-Korean-0.0.2 perl module을 PHP로 포팅한 것이다.
* 양력 기준으로 1391-02-05 부터 2050-12-31 까지의 기간만 가능하며, 절기, 합삭/망
* 정보, 세차/월간/일진등의 정보는 oops\Lunar pear package를 이용하도록 한다.
* 이 패키지는 pear/Lunar package의 확장을 위하여 제작이 되었으며, 라이센스 문제로
* pear/Lunar package와 별도의 패키지로 제작이 되었다. 물론 독립적으로 사용해도 무방
* @package oops/KASI/Lunar
* @author JoungKyun.Kim <http://oops.org>
* @copyright (c) 2024, OOPS.org
* @license GPL (or Perl license)
* @example KASI-Lunar/tests/test.php Sample code
// {{{ +-- public properties
// {{{ +-- public version (void)
* @return string KASI_Lunar 버전
# 관리를 위해 꼭 single quote 를 사용한다!
// {{{ +-- public (object) tolunar ($v = null)
* {@example KASI-Lunar/tests/test.php 21 51}
* @return stdClass 음력 날자 정보 반환
* [fmt] => 2013-06-09 // YYYY-MM-DD 형식의 음력 날자
* [jd] => 2456582 // 율리어스 적일
* [lmonth] => 1 // 평달/큰달 여부
* - unixstmap (1970년 12월 15일 이후부터 가능)
* - 1582년 10월 15일 이전의 날자는 율리우스력의 날자로 취급함.
* 예.. 10월 14일은 그레고리력 10월 24일
public function tolunar ($v = null) {
list ($y, $m, $d) = $this->toargs ($v);
$jd = $this->cal2jd (array ($y, $m, $d));
if ( $jd < Tables::$MinDate || $jd > Tables::$MaxDate ) {
'Invalid date period. Valid period is from 1391-02-05 to 2050-12-31 with solar',
$day = $jd - Tables::$MinDate;
$mon = $this->bisect (Tables::$month, $day);
$yer = $this->bisect (Tables::$year, $mon);
$month = $mon - Tables::$year[$yer] + 1;
$days = $day - Tables::$month[$mon] + 1;
$lmoon = Tables::$month[$mon+ 1] - Tables::$month[$mon];
$lmoon = ($lmoon == 29) ? false : true;
if ( Tables::$leap[$yer] != 0 && Tables::$leap[$yer] <= $month ) {
if ( Tables::$leap[$yer] == $month )
$year = $yer + Tables::$BaseYear;
'fmt' => $this->datestring ($year, $month, $days, '-'),
// {{{ +-- public (object) tosolar ($v = null, $leap = false)
* {@example KASI-Lunar/tests/test.php 21 51}
* @return stdClass 양력 날자 정보 object 반환
* [fmt] => 2013-06-09 // YYYY-MM-DD 형식의 음력 날자
* [jd] => 2456527 // 율리어스 적일
* [year] => 2013 // 양력 연도
* - unixstmap (1970년 12월 15일 이후부터 가능)
public function tosolar ($v = null, $leap = false) {
list ($y, $m, $d) = $this->toargs ($v, true);
$yer = $y - Tables::$BaseYear;
if ( $leap && (Tables::$leap[$yer] - 1) != $m )
$month = Tables::$year[$yer] + $m - 1;
if ( $leap && ($m + 1) == Tables::$leap[$yer] )
else if ( Tables::$leap[$yer] && Tables::$leap[$yer] <= $m )
$day = Tables::$month[$month] + $d - 1;
if ( $d < 1 || $day >= Tables::$month[$month+ 1] ) {
throw new \ myException ('Invalid day', E_USER_WARNING);
'fmt' => $this->datestring ($r->year, $r->month, $r->day, '-'),
// {{{ +-- public (int) cal2jd ($v)
* @return int 율리우스 적일(integer)
* @param array 연/월/일 배열 : array ($y, $m, $d)
if ( ! extension_loaded ('calendar') ) {
throw new \ myException ('Don\'t support the calendar extension in PHP', E_USER_WARNING);
$datestr = $this->datestring ($y, $m, $d);
if ( $datestr < 15821015 ) {
if ( $datestr > 15821004 ) {
$func = $julian ? 'JulianToJD' : 'GregorianToJD';
$r = $func ((int) $m, (int) $d, (int) $y);
// {{{ +-- public (object) cal4jd ($jd = null)
* 율리우스 적일을 율리우스력 또는 그레고리력으로 변환
* oops\KASI\Lunar::jd2cal 의 alias method로 deprecated
* 되었기 때문에 jd2cal method로 변경 해야 함.
* @return stdClass 율리우스력 또는 그레고리력 정보
* [year] => 2013 // 양력 연도
* @param int 율리우스 적일. [default: 현재날의 적일]
* @deprecated deprecated since version 1.0.1
public function cal4jd ($jd = null) {
// {{{ +-- public (object) jd2cal ($jd = null)
* 율리우스 적일을 율리우스력 또는 그레고리력으로 변환
* @return stdClass 율리우스력 또는 그레고리력 정보
* [year] => 2013 // 양력 연도
* @param int 율리우스 적일. [default: 현재날의 적일]
public function jd2cal ($jd = null) {
throw new \ myException ('Don\'t support the calendar extension in PHP', E_USER_WARNING);
$cvt = ($jd > 2299160) ? CAL_GREGORIAN : CAL_JULIAN;
// {{{ +-- public (int) jd2week ($jd = null)
* @param int 율리우스 적일. [default: 현재날의 적일]
public function jd2week ($jd = null) {
return fmod ($jd + 1, 7);
// {{{ +-- public (object) season ($so, $year = null)
* [hname] => 立春 // 절기 한지 이름
* [stamp] => 1073348340 // 입절시각. Unix timestamp
* [date] => 2004-02-04 20:56 // 입절 시각. YYYY-MM-DD HH:mm 형식의 양력 날자
* [year] => 2004 // 입절 시각 연도
* [month] => 2 // 입절 시각 월
* [hour] => 20 // 입절 시각 시간
public function season ($name, $year = null) {
if ( $year > 2026 || $year < 2004 ) {
'Support between 2004 and 2026',
"Invalid Invalid season name ($name).",
# 절기 배열은 2004년이 첫번째 배열이다.
$so = Seasons::$so24[$sid][$id];
$t = preg_split ('/[-]/', date ('Y-m-d-H-i-s', $so));
'date' => sprintf ("%d-%02d-%02d %02d:%02d", $t[0], $t[1], $t[2], $t[3], $t[4]),
// {{{ +-- private (array) toargs ($v, $lanur = false)
* 입력된 날자 형식을 연/월/일의 멤버를 가지는 배열로 반환한다.
* 입력된 변수 값은 YYYY-MM-DD 형식으로 변환 된다.
* {@example Lunar/tests/sample.php 30 25}
* - unixstmap (1970년 12월 15일 이후부터 가능)
private function toargs (&$v, $lunar = false) {
$y = (int) date ('Y', $v);
$m = (int) date ('m', $v);
$d = (int) date ('d', $v);
if ( preg_match ('/^(-?[0-9]{1,4})[\/-]?([0-9]{1,2})[\/-]?([0-9]{1,2})$/', trim ($v), $match) ) {
list ($y, $m, $d) = $match;
throw new \ myException ('Invalid Date Format', E_USER_WARNING);
if ( ! $lunar && $y > 1969 && $y < 2038 ) {
$fixed = mktime (0, 0, 0, $m, $d, $y);
$y = (int) date ('Y', $fixed);
$m = (int) date ('m', $fixed);
$d = (int) date ('d', $fixed);
if ( $m > 12 || $d > 31 ) {
throw new \ myException ('Invalid Date Format', E_USER_WARNING);
$v = $this->datestring ($y, $m, $d, '-');
return array ($y, $m, $d);
// {{{ +-- private bisect ($a, $x)
private function bisect ($a, $x) {
$mid = (int) (($lo + $hi) / 2);
// {{{ +-- private datestring ($y, $m, $d)
private function datestring ($y, $m, $d, $dash = '') {
return $y . $dash . $m . $dash . $d;
|