oops-KASI-Lunar
[ class tree: oops-KASI-Lunar ] [ index: oops-KASI-Lunar ] [ all elements ]

Source for file KASI_Lunar.php

Documentation is available at KASI_Lunar.php

  1. <?php
  2. /**
  3.  * Project: oops\KASI\Lunar:: 한국천문연구원 데이터를 기반으로 한 음/양력 변환 클래스<br>
  4.  * Files:   Lnuar.php<br>
  5.  * Dependency:
  6.  *   - {@link http://pear.oops.org/docs/li_myException.html oops/myException}
  7.  *   - {@link http://kr1.php.net/manual/en/book.calendar.php calendar extension}
  8.  *
  9.  * 이 패키지는 한국천문연구원의 음양력 데이터를 기반으로 하여 양력/음열간의 변환을
  10.  * 제공하며, aero님의 Date-Korean-0.0.2 perl module을 PHP로 포팅한 것이다.
  11.  *
  12.  * 양력 기준으로 1391-02-05 부터 2050-12-31 까지의 기간만 가능하며, 절기, 합삭/망
  13.  * 정보, 세차/월간/일진등의 정보는 oops\Lunar pear package를 이용하도록 한다.
  14.  *
  15.  * 이 패키지는 pear/Lunar package의 확장을 위하여 제작이 되었으며, 라이센스 문제로
  16.  * pear/Lunar package와 별도의 패키지로 제작이 되었다.
  17.  *
  18.  * @category    Calendar
  19.  * @package     oops\KASI\Lunar
  20.  * @author      JoungKyun.Kim <http://oops.org>
  21.  * @copyright   (c) 2024, OOPS.org
  22.  * @license     GPL (or Perl license)
  23.  * @link        https://github.com/OOPS-ORG-PHP/KASI-Lunar
  24.  * @since       File available since release 0.0.1
  25.  * @example     KASI-Lunar/tests/test.php Sample code
  26.  * @filesource
  27.  */
  28.  
  29. /**
  30.  * Namespace oops\KASI;
  31.  */
  32. namespace oops\KASI;
  33.  
  34. /**
  35.  * import myException class
  36.  */
  37. require_once 'myException.php';
  38. set_error_handler('myException::myErrorHandler');
  39.  
  40. /**
  41.  * import Lunar API
  42.  */
  43. require_once 'KASI_Lunar/Lunar_Tables.php';
  44. require_once 'KASI_Lunar/Lunar_Seasons.php';
  45.  
  46.  
  47. /**
  48.  * oops\KASI pear package의 main class
  49.  *
  50.  * 한국천문연구원 데이터를 기반으로 한 음/양력 변환 클래스
  51.  *
  52.  * 이 패키지는 한국천문연구원의 음양력 데이터를 기반으로 하여 양력/음열간의 변환을
  53.  * 제공하며, aero님의 Date-Korean-0.0.2 perl module을 PHP로 포팅한 것이다.
  54.  *
  55.  * 양력 기준으로 1391-02-05 부터 2050-12-31 까지의 기간만 가능하며, 절기, 합삭/망
  56.  * 정보, 세차/월간/일진등의 정보는 oops\Lunar pear package를 이용하도록 한다.
  57.  *
  58.  * 이 패키지는 pear/Lunar package의 확장을 위하여 제작이 되었으며, 라이센스 문제로
  59.  * pear/Lunar package와 별도의 패키지로 제작이 되었다. 물론 독립적으로 사용해도 무방
  60.  * 하다.
  61.  *
  62.  * @package     oops/KASI/Lunar
  63.  * @author      JoungKyun.Kim <http://oops.org>
  64.  * @copyright   (c) 2024, OOPS.org
  65.  * @license     GPL (or Perl license)
  66.  * @example     KASI-Lunar/tests/test.php Sample code
  67.  */
  68.  
  69. class Lunar {
  70.     // {{{ +-- public properties
  71.     /**#@+
  72.      * @access public
  73.      */
  74.     /**
  75.      * enable exception
  76.      * @var boolean 
  77.      */
  78.     public $is_exception = true;
  79.     /**#@-*/
  80.     // }}}
  81.  
  82.     // {{{ +-- public version (void)
  83.     /**
  84.      * KASI_Lunar 의 현재 버전을 출력
  85.      *
  86.      * @access public
  87.      * @return string  KASI_Lunar 버전
  88.      */
  89.     public function version ({
  90.         # 관리를 위해 꼭 single quote 를 사용한다!
  91.         return '2.0.1';
  92.     }
  93.     // }}}
  94.  
  95.     // {{{ +-- public (object) tolunar ($v = null)
  96.     /**
  97.      * 양력 날자를 음력으로 변환
  98.      *
  99.      * 예제:
  100.      * {@example KASI-Lunar/tests/test.php 21 51}
  101.      *
  102.      * @access public
  103.      * @return stdClass    음력 날자 정보 반환
  104.      *
  105.      *    <pre>
  106.      *    stdClass Object
  107.      *    (
  108.      *        [fmt]    => 2013-06-09       // YYYY-MM-DD 형식의 음력 날자
  109.      *        [jd]     => 2456582          // 율리어스 적일
  110.      *        [year]   => 2013             // 연도
  111.      *        [month]  => 6                // 월
  112.      *        [day]    => 9                // 일
  113.      *        [leap]   =>                  // 음력 윤달 여부
  114.      *        [lmonth] => 1                // 평달/큰달 여부
  115.      *    )
  116.      *    </pre>
  117.      *
  118.      * @param int|string  날자형식
  119.      *    - unixstmap (1970년 12월 15일 이후부터 가능)
  120.      *    - Ymd or Y-m-d
  121.      *    - null data (현재 시간)
  122.      *    - 1582년 10월 15일 이전의 날자는 율리우스력의 날자로 취급함.
  123.      *      예.. 10월 14일은 그레고리력 10월 24일
  124.      */
  125.     public function tolunar ($v null{
  126.         list ($y$m$d$this->toargs ($v);
  127.  
  128.         $jd $this->cal2jd (array ($y$m$d));
  129.  
  130.         if $jd Tables::$MinDate || $jd Tables::$MaxDate {
  131.             if $this->is_exception == true {
  132.                 throw new \myException (
  133.                     'Invalid date period. Valid period is from 1391-02-05 to 2050-12-31 with solar',
  134.                     E_USER_WARNING
  135.                 );
  136.             }
  137.             return false;
  138.         }
  139.  
  140.         $day $jd Tables::$MinDate;
  141.  
  142.         $mon $this->bisect (Tables::$month$day);
  143.         $yer $this->bisect (Tables::$year$mon);
  144.  
  145.         $month $mon Tables::$year[$yer1;
  146.         $days  $day  Tables::$month[$mon1;
  147.  
  148.         // 큰달 작은달 체크
  149.         $lmoon Tables::$month[$mon+1Tables::$month[$mon];
  150.         $lmoon ($lmoon == 29false true;
  151.  
  152.         // 윤달 체크
  153.         $leap false;
  154.         if Tables::$leap[$yer!= && Tables::$leap[$yer<= $month {
  155.             if Tables::$leap[$yer== $month )
  156.                 $leap true;
  157.             $month -= 1;
  158.         }
  159.  
  160.         $year $yer Tables::$BaseYear;
  161.  
  162.         return (object) array (
  163.             'fmt'   => $this->datestring ($year$month$days'-'),
  164.             'jd'    => $jd,
  165.             'year'  => $year,
  166.             'month' => $month,
  167.             'day'   => $days,
  168.             'week'  => $this->jd2week ($jd),
  169.             'leap'  => $leap,
  170.             'lmoon' => $lmoon
  171.         );
  172.     }
  173.     // }}}
  174.  
  175.     // {{{ +-- public (object) tosolar ($v = null, $leap = false)
  176.     /**
  177.      * 음력 날자를 양력으로 변환.
  178.      *
  179.      * 예제:
  180.      * {@example KASI-Lunar/tests/test.php 21 51}
  181.      *
  182.      * @access public
  183.      * @return stdClass    양력 날자 정보 object 반환
  184.      *
  185.      *    <pre>
  186.      *    stdClass Object
  187.      *    (
  188.      *        [fmt]   => 2013-06-09       // YYYY-MM-DD 형식의 음력 날자
  189.      *        [jd]    => 2456527          // 율리어스 적일
  190.      *        [year]  => 2013             // 양력 연도
  191.      *        [month] => 7                // 월
  192.      *        [day]   => 16               // 일
  193.      *        [week]  => 6                // 요일
  194.      *    )
  195.      *    </pre>
  196.      *
  197.      * @param int|string날자형식
  198.      *
  199.      *    - unixstmap (1970년 12월 15일 이후부터 가능)
  200.      *    - Ymd or Y-m-d
  201.      *    - null data (현재 시간)
  202.      *
  203.      * @param bool 윤달여부
  204.      */
  205.     public function tosolar ($v null$leap false{
  206.         list ($y$m$d$this->toargs ($vtrue);
  207.  
  208.         $yer $y Tables::$BaseYear;
  209.  
  210.         // 윤달이 아닐 경우 값 보정
  211.         if $leap && (Tables::$leap[$yer1!= $m )
  212.              $leap false;
  213.  
  214.         $month Tables::$year[$yer$m 1;
  215.  
  216.         if $leap && ($m 1== Tables::$leap[$yer)
  217.             $month++;
  218.         else if Tables::$leap[$yer&& Tables::$leap[$yer<= $m )
  219.             $month++;
  220.  
  221.         $day Tables::$month[$month$d 1;
  222.         if $d || $day >= Tables::$month[$month+1{
  223.             throw new \myException ('Invalid day'E_USER_WARNING);
  224.             return false;
  225.         }
  226.  
  227.         $day += Tables::$MinDate;
  228.         $r $this->jd2cal ($day);
  229.  
  230.         return (object) array (
  231.             'fmt'   => $this->datestring ($r->year$r->month$r->day'-'),
  232.             'jd'    => $day,
  233.             'year'  => $r->year,
  234.             'month' => $r->month,
  235.             'day'   => $r->day,
  236.             'week'  => $r->week
  237.         );
  238.     }
  239.     // }}}
  240.  
  241.     // {{{ +-- public (int) cal2jd ($v)
  242.     /**
  243.      * 날자를 율리우스 적일로 변환
  244.      *
  245.      * @access public
  246.      * @return int 율리우스 적일(integer)
  247.      * @param array 연/월/일 배열 : array ($y, $m, $d)
  248.      */
  249.     public function cal2jd ($v{
  250.         if extension_loaded ('calendar') ) {
  251.             if $this->is_exception == true )
  252.                 throw new \myException ('Don\'t support the calendar extension in PHP'E_USER_WARNING);
  253.             return false;
  254.         }
  255.  
  256.         list ($y$m$d$v;
  257.  
  258.         $julian false;
  259.  
  260.         $datestr $this->datestring ($y$m$d);
  261.         $julian false;
  262.         if $datestr 15821015 {
  263.             $julian true;
  264.             if $datestr 15821004 {
  265.                 $d += 10;
  266.                 $julian false;
  267.             }
  268.         }
  269.  
  270.         $old date_default_timezone_get ();
  271.         date_default_timezone_set ('UTC');
  272.  
  273.         $func $julian 'JulianToJD' 'GregorianToJD';
  274.         if $y )
  275.             $y--;
  276.         $r $func ((int) $m(int) $d(int) $y);
  277.  
  278.         date_default_timezone_set ($old);
  279.         return $r;
  280.     }
  281.     // }}}
  282.  
  283.     // {{{ +-- public (object) cal4jd ($jd = null)
  284.     /**
  285.      * 율리우스 적일을 율리우스력 또는 그레고리력으로 변환
  286.      *
  287.      * oops\KASI\Lunar::jd2cal 의 alias method로 deprecated
  288.      * 되었기 때문에 jd2cal method로 변경 해야 함.
  289.      *
  290.      * 1.0.2 부터 삭제 예정
  291.      *
  292.      * @access public
  293.      * @return stdClass    율리우스력 또는 그레고리력 정보
  294.      *
  295.      *    <pre>
  296.      *    stdClass Object
  297.      *    (
  298.      *        [year] => 2013              // 양력 연도
  299.      *        [month] => 7                // 월
  300.      *        [day] => 16                 // 일
  301.      *        [week] => 6                 // 요일
  302.      *    )
  303.      *    </pre>
  304.      *
  305.      * @param int 율리우스 적일. [default: 현재날의 적일]
  306.      * @deprecated deprecated since version 1.0.1
  307.      */
  308.     public function cal4jd ($jd null{
  309.         return $this->jd2cal ($jd);
  310.     }
  311.     // }}}
  312.  
  313.     // {{{ +-- public (object) jd2cal ($jd = null)
  314.     /**
  315.      * 율리우스 적일을 율리우스력 또는 그레고리력으로 변환
  316.      *
  317.      * @access public
  318.      * @return stdClass    율리우스력 또는 그레고리력 정보
  319.      *
  320.      *    <pre>
  321.      *    stdClass Object
  322.      *    (
  323.      *        [year] => 2013              // 양력 연도
  324.      *        [month] => 7                // 월
  325.      *        [day] => 16                 // 일
  326.      *        [week] => 6                 // 요일
  327.      *    )
  328.      *    </pre>
  329.      *
  330.      * @param int 율리우스 적일. [default: 현재날의 적일]
  331.      */
  332.     public function jd2cal ($jd null{
  333.         if extension_loaded ('calendar') ) {
  334.             if $this->is_exception == true )
  335.                 throw new \myException ('Don\'t support the calendar extension in PHP'E_USER_WARNING);
  336.             return false;
  337.         }
  338.  
  339.         if $jd )
  340.             $jd unixtojd (time ());
  341.  
  342.         $cvt ($jd 2299160CAL_GREGORIAN CAL_JULIAN;
  343.         $r = (object) cal_from_jd ($jd$cvt);
  344.         if $r->year )
  345.             $r->year++;
  346.  
  347.         return (object) array (
  348.             'year'  => $r->year,
  349.             'month' => $r->month,
  350.             'day'   => $r->day,
  351.             'week'  => $r->dow
  352.         );
  353.     }
  354.     // }}}
  355.  
  356.     // {{{ +-- public (int) jd2week ($jd = null)
  357.     /**
  358.      * 율리우스 적일로 요일 정보를 구함
  359.      *
  360.      * @access public
  361.      * @return int         요일 배열 인덱스
  362.      *
  363.      *  0(일) ~ 6(토)
  364.      *
  365.      * @param int 율리우스 적일. [default: 현재날의 적일]
  366.      */
  367.     public function jd2week ($jd null{
  368.         if $jd {
  369.             $today date ('Y-m-d'time ());
  370.             $t preg_split ('/-/'$today);
  371.             $jd $this->cal2jd ($t);
  372.         }
  373.  
  374.         return fmod ($jd 17);
  375.         /*
  376.         $mjd = $jd - 2400000.5;
  377.         $widx = $mjd % 7 + 3;
  378.         if ( $widx < 3 )
  379.             $widx += 7;
  380.  
  381.         if ( $widx > 6 )
  382.             $widx -= 7;
  383.  
  384.         return $widx;
  385.          */
  386.     }
  387.     // }}}
  388.  
  389.     // {{{ +-- public (object) season ($so, $year = null)
  390.     /**
  391.      * 연도별 절기의 입절시각을 구함
  392.      *
  393.      * @access public
  394.      * @return array|false
  395.      *
  396.      *    <pre>
  397.      *    stdClass Object
  398.      *    (
  399.      *        [name]   => 입춘             // 절기 이름
  400.      *        [hname]  => 立春             // 절기 한지 이름
  401.      *        [stamp]  => 1073348340       // 입절시각. Unix timestamp
  402.      *        [date]   => 2004-02-04 20:56 // 입절 시각. YYYY-MM-DD HH:mm 형식의 양력 날자
  403.      *        [year]   => 2004             // 입절 시각 연도
  404.      *        [month]  => 2                // 입절 시각 월
  405.      *        [day]    => 4                // 입절 시각 일
  406.      *        [hour]   => 20               // 입절 시각 시간
  407.      *        [min]    => 56               // 입절 시각 분
  408.      *    )
  409.      *    </pre>
  410.      *
  411.      * @param int 연도
  412.      * @param string 절기 이름
  413.      */
  414.     public function season ($name$year null{
  415.         if $year == null )
  416.             $year date ('%Y'time ());
  417.  
  418.         if $year 2026 || $year 2004 {
  419.             if $this->is_exception == true {
  420.                 throw new \myException (
  421.                     'Support between 2004 and 2026',
  422.                     E_USER_WARNING
  423.                 );
  424.             }
  425.             return false;
  426.         }
  427.  
  428.         $id array_search ($nameSeasons::$so24n);
  429.         if $id === false {
  430.             if $this->is_exception == true {
  431.                 throw new \myException (
  432.                     "Invalid Invalid season name ($name).",
  433.                     E_USER_WARNING
  434.                 );
  435.             }
  436.             return false;
  437.         }
  438.         $hid Seasons::$so24hn[$id];
  439.         # 절기 배열은 2004년이 첫번째 배열이다.
  440.         $sid $year 2004;
  441.         $so Seasons::$so24[$sid][$id];
  442.  
  443.         $t preg_split ('/[-]/'date ('Y-m-d-H-i-s'$so));
  444.  
  445.         return (object) array (
  446.             'name'  => $name,
  447.             'hname' => $hid,
  448.             'stamp' => $so,
  449.             'date'  => sprintf ("%d-%02d-%02d %02d:%02d"$t[0]$t[1]$t[2]$t[3]$t[4]),
  450.             'year'  => $t[0],
  451.             'month' => $t[1],
  452.             'day'   => $t[2],
  453.             'hour'  => $t[3],
  454.             'min'   => $t[4]
  455.         );
  456.     }
  457.     // }}}
  458.  
  459.     // {{{ +-- private (array) toargs ($v, $lanur = false)
  460.     /**
  461.      * 입력된 날자 형식을 연/월/일의 멤버를 가지는 배열로 반환한다.
  462.      * 입력된 변수 값은 YYYY-MM-DD 형식으로 변환 된다.
  463.      *
  464.      * 예제:
  465.      * {@example Lunar/tests/sample.php 30 25}
  466.      *
  467.      * @access public
  468.      * @return array 
  469.      *    <pre>
  470.      *        Array
  471.      *        (
  472.      *            [0] => 2013
  473.      *            [1] => 7
  474.      *            [2] => 16
  475.      *        )
  476.      *    </pre>
  477.      * @param string|int날자형식
  478.      *
  479.      *    - unixstmap (1970년 12월 15일 이후부터 가능)
  480.      *    - Ymd or Y-m-d
  481.      *    - null data (현재 시간)
  482.      */
  483.     private function toargs (&$v$lunar false{
  484.         if $v == null {
  485.             $y = (int) date ('Y');
  486.             $m = (int) date ('m');
  487.             $d = (int) date ('d');
  488.         else {
  489.             if $lunar {
  490.  
  491.             }
  492.  
  493.             if is_numeric ($v&& $v 30000000 {
  494.                 // unit stamp ?
  495.                 $y = (int) date ('Y'$v);
  496.                 $m = (int) date ('m'$v);
  497.                 $d = (int) date ('d'$v);
  498.             else {
  499.                 if preg_match ('/^(-?[0-9]{1,4})[\/-]?([0-9]{1,2})[\/-]?([0-9]{1,2})$/'trim ($v)$match) ) {
  500.                     array_shift ($match);
  501.                     list ($y$m$d$match;
  502.                 else {
  503.                     if $this->is_exception == true )
  504.                         throw new \myException ('Invalid Date Format'E_USER_WARNING);
  505.                     return false;
  506.                 }
  507.             }
  508.  
  509.             if $lunar && $y 1969 && $y 2038 {
  510.                 $fixed mktime (000$m$d$y);
  511.                 $y = (int) date ('Y'$fixed);
  512.                 $m = (int) date ('m'$fixed);
  513.                 $d = (int) date ('d'$fixed);
  514.             else {
  515.                 if $m 12 || $d 31 {
  516.                     if $this->is_exception == true )
  517.                         throw new \myException ('Invalid Date Format'E_USER_WARNING);
  518.                     return false;
  519.                 }
  520.             }
  521.         }
  522.         $v $this->datestring ($y$m$d'-');
  523.  
  524.         return array ($y$m$d);
  525.     }
  526.     // }}}
  527.  
  528.     // {{{ +-- private bisect ($a, $x)
  529.     private function bisect ($a$x{
  530.         $lo 0;
  531.         $hi count ($a);
  532.  
  533.         while $lo $hi {
  534.             $mid = (int) (($lo $hi2);
  535.             if $x $a[$mid)
  536.                 $hi $mid;
  537.             else
  538.                 $lo $mid 1;
  539.         }
  540.  
  541.         return --$lo;
  542.     }
  543.     // }}}
  544.  
  545.     // {{{ +-- private datestring ($y, $m, $d)
  546.     private function datestring ($y$m$d$dash ''{
  547.         if $m 10 )
  548.             $m '0' . (int) $m;
  549.         if $d 10 )
  550.             $d '0' . (int) $d;
  551.  
  552.         return $y $dash $m $dash $d;
  553.     }
  554.     // }}}
  555. }
  556. ?>

Documentation generated on Fri, 30 Aug 2024 06:10:33 +0900 by phpDocumentor 1.4.4