code.fastix.org

Dateiansicht:

Datei:Projekte -> PHP:Feiertage -> feiertage.php
md5:3b340d9805c0d89185f8ff39bc37a4e5
sha1:01cbcd11a1d0dcba1eee37110f248a799a516090
  1. <?php
  2. /**
  3. * @description: Skript, welches Feiertage ermittelt.
  4. * @author: Jörg Reinholz, fastix WebDesign & Consult, Kassel - http://www.fastix.org/
  5. * @version: 0.7.1 (BETA)
  6. * @needed php >= 5.2.1 optimal: 64bit
  7. **/
  8.  
  9.  
  10. class feiertage
  11. {
  12.     private $iniFile = 'deutscheFeiertage.ini';
  13.     private $jahr = false;
  14.     private $advent4;
  15.     private $feiertage = array();
  16.     protected $cacheFile;
  17.     protected $cacheFileName;
  18.     protected $code;
  19.     protected $arrShowOnlyTypes = false;
  20.     protected $monthNames = array();
  21.     protected $wdNames = array();
  22.  
  23.     protected $wdValues = array();
  24.  
  25.     public function __construct( $jahr = false ) {
  26.         $this -> setJahr($jahr);
  27.         $this -> wdNames['0'] = $wdNames['7'] = 'Sonntag';
  28.         $this -> wdNames[1] = 'Montag';
  29.         $this -> wdNames[2] = 'Dienstag';
  30.         $this -> wdNames[3] = 'Mittwoch';
  31.         $this -> wdNames[4] = 'Donnerstag';
  32.         $this -> wdNames[5] = 'Freitag';
  33.         $this -> wdNames[6] = 'Sonnabend';
  34.  
  35.         $this -> monthNames[0] = 'Januar';
  36.         $this -> monthNames[1] = 'Februar';
  37.         $this -> monthNames[2] = 'März';
  38.         $this -> monthNames[3] = 'April';
  39.         $this -> monthNames[4] = 'Mai';
  40.         $this -> monthNames[5] = 'Juni';
  41.         $this -> monthNames[6] = 'Juli';
  42.         $this -> monthNames[7] = 'August';
  43.         $this -> monthNames[8] = 'September';
  44.         $this -> monthNames[9] = 'Oktober';
  45.         $this -> monthNames[10] = 'November';
  46.         $this -> monthNames[11] = 'Dezember';
  47.     }
  48.  
  49.     public function easterDate($y) {
  50.         return ( mktime(0, 0, 0, 3, 21 + easter_days( $y ), $y ) );
  51.     }
  52.  
  53.     public function wdnameToValue($str) {
  54.         $wdValues['mo'] = 1;
  55.         $wdValues['mon'] = 1;
  56.         $wdValues['monday'] = 1;
  57.         $wdValues['montag'] = 1;
  58.  
  59.         $wdValues['di'] = 2;
  60.         $wdValues['tue'] = 2;
  61.         $wdValues['tuesday'] = 2;
  62.         $wdValues['mittwoch'] = 2;
  63.  
  64.         $wdValues['mi'] = 3;
  65.         $wdValues['wed'] = 3;
  66.         $wdValues['wednesday'] = 3;
  67.         $wdValues['mittwoch'] = 3;
  68.  
  69.         $wdValues['do'] = 4;
  70.         $wdValues['thu'] = 4;
  71.         $wdValues['thursday'] = 4;
  72.         $wdValues['donnerstag'] = 4;
  73.  
  74.         $wdValues['fr'] = 5;
  75.         $wdValues['fre'] = 5;
  76.         $wdValues['freeday'] = 5;
  77.         $wdValues['freitag'] = 5;
  78.  
  79.         $wdValues['sa'] = 6;
  80.         $wdValues['sat'] = 6;
  81.         $wdValues['Saturday'] = 6;
  82.         $wdValues['Samstag'] = 6;
  83.         $wdValues['Sonnabend'] = 6;
  84.  
  85.         $wdValues['so'] = 7;
  86.         $wdValues['son'] = 7;
  87.         $wdValues['sonday'] = 7;
  88.         $wdValues['sonntag'] = 7;
  89.  
  90.         $s = strtolower(trim($str));
  91.         if ( isset( $wdValues[$s] ) ) {
  92.             return $wdValues[$s];
  93.         } else {
  94.             return $str;
  95.         }
  96.     }
  97.  
  98.  
  99.     public function setJahr( $jahr = false ) {
  100.  
  101.         if ( false === $jahr) { $jahr = date('Y'); }
  102.  
  103.         if ( $jahr !== $this -> jahr ) {
  104.                 $this -> jahr = $jahr;
  105.         }
  106.         $this -> cacheFileName = $this -> iniFile . '.php';
  107.         $this -> cacheFile = __DIR__ . '/cache/' . $this -> jahr . '-' . $this -> iniFile . '.php';
  108.  
  109.         $iniFileDate = filemtime($this -> iniFile);
  110.         if ( is_file($this -> cacheFile) ) {
  111.             $cacheFileDate = filemtime($this -> cacheFile);
  112.         }
  113.  
  114.         if ( ! isset($cacheFileDate) or $cacheFileDate < $iniFileDate ) {
  115.  
  116.             try {
  117.                 if ( ! mktime(1, 1, 1, 12, 31, $jahr ) ) {
  118.                     throw new Exception('Das übergebene Jahr ' . $jahr . ' ist auf 32-Bit-Systemen ungültig. Gültig sind Jahre zwischen 1970 und 2037.');
  119.                 }
  120.             } catch ( Exception $e ) {
  121.                 echo 'Fatal: ',  $e->getMessage(), ' Datei: ' , $e->getFile(), ' Zeile: ', $e->getLine(), "\n";
  122.                 exit;
  123.             }
  124.  
  125.  
  126.             if ( ! isset($ini) ) {
  127.                 $ini = parse_ini_file( $this -> iniFile, true );
  128.             }
  129.  
  130.             $fromAdvent4 = $ini['fromAdvent4'];
  131.             $dLastAdvent = 24 - date( 'w', mktime( 0, 0, 0, 12, 24, $jahr ) );
  132.             $mLastAdvent = 12;
  133.  
  134.             for ( $i = 0; $i < count($fromAdvent4['name']); $i++ ) {
  135.                 $offset = $fromAdvent4 ['offset'][$i];
  136.                 $dto = mktime ( 0, 0, 0, $mLastAdvent, ( $dLastAdvent + $offset ), $this -> jahr );
  137.                 $m = date( 'n', $dto );
  138.                 $d = date( 'j', $dto );
  139.                 $notBefore = intval( $fromAdvent4['notBefore'][$i] );
  140.                 if ( $notBefore == 0 ) { $notBefore = -99999999; }
  141.                 $notAfter = intval( $fromAdvent4['notAfter'][$i] );
  142.                 if ( $notAfter == 0 ) { $notAfter = 99999999; }
  143.                 if ( $notBefore <= $jahr && $notAfter >= $jahr ) {
  144.                     $name =   $fromAdvent4['name'][$i];
  145.                     if ( isset( $fromAdvent4['codes'][$i] ) ) {
  146.                         $codes = preg_replace('/[^A-Za-z0-9_]+/' , ',' ,$fromAdvent4['codes'][$i]);
  147.                         $arCodes = explode( ',', $codes ) ;
  148.                     }
  149.                     $this -> addFeiertag (intval($m), intval($d), $name, $arCodes);
  150.                 }
  151.             }
  152.  
  153.             $fromEaster = $ini['fromEaster'];
  154.             $dtoEasterSonnday =  $this -> easterDate( $this -> jahr);
  155.             $mEasterSonnday = date('n', $dtoEasterSonnday);
  156.             $dEasterSonnday = date('j', $dtoEasterSonnday);
  157.  
  158.             for ( $i = 0; $i < count($fromEaster['name']); $i++ ) {
  159.                 $notBefore = intval( $fromEaster['notBefore'][$i] );
  160.                 if ( $notBefore == 0 ) { $notBefore = -99999999; }
  161.                 $notAfter = intval( $fromEaster['notAfter'][$i] );
  162.                 if ( $notAfter == 0 ) { $notAfter = 99999999; }
  163.                 if ( $notBefore <= $jahr && $notAfter >= $jahr ) {
  164.                     $name =   $fromEaster['name'][$i];
  165.                     $offset = $fromEaster['offset'][$i];
  166.                     $dto = mktime ( 0, 0, 0, $mEasterSonnday, ($dEasterSonnday + $offset), $this -> jahr );
  167.                     $m = date( 'n', $dto );
  168.                     $d = date( 'j', $dto );
  169.                     $arCodes=array();
  170.                     if (  isset( $fromEaster['codes'][$i] ) ) {
  171.                         $codes = preg_replace('/[^A-Za-z0-9_]+/' , ',' ,$fromEaster['codes'][$i]);
  172.                         $arCodes = explode( ',', $codes ) ;
  173.                     }
  174.                     $this -> addFeiertag (intval($m), intval($d), $name, $arCodes);
  175.                 }
  176.             }
  177.  
  178.             $fixDays = $ini['fix'];
  179.             for ( $i = 0; $i < count($fixDays['name']); $i++ ) {
  180.                 $m    = intval( $fixDays['m'][$i] );
  181.                 $d    = intval( $fixDays['d'][$i] );
  182.                 $notBefore = intval( $fixDays['notBefore'][$i] );
  183.                 if ( $notBefore == 0 ) { $notBefore = -99999999; }
  184.                 $notAfter = intval( $fixDays['notAfter'][$i] );
  185.                 if ( $notAfter == 0 ) { $notAfter = 99999999; }
  186.                 if ( $notBefore <= $jahr && $notAfter >= $jahr ) {
  187.                     $name = $fixDays['name'][$i];
  188.                     $arCodes=array();
  189.                     if ( isset( $fixDays['codes'][$i] ) ) {
  190.                         $codes = preg_replace('/[^A-Za-z0-9_]+/' , ',' ,$fixDays['codes'][$i]);
  191.                         $arCodes = explode( ',', $codes ) ;
  192.                     }
  193.                     $this -> addFeiertag (intval($m), intval($d), $name, $arCodes);
  194.                 }
  195.             }
  196.  
  197.             $MO_WT_WO = $ini['MO_WT_WO'];
  198.             for ( $i = 0; $i < count($MO_WT_WO['name']); $i++ ) {
  199.                 $notBefore = intval( $MO_WT_WO['notBefore'][$i] );
  200.                 if ( $notBefore == 0 ) { $notBefore = -99999999; }
  201.                 $notAfter = intval( $MO_WT_WO['notAfter'][$i] );
  202.                 if ( $notAfter == 0 ) { $notAfter = 99999999; }
  203.                 if ( $notBefore <= $jahr && $notAfter >= $jahr ) {
  204.                     $ar=explode(',', $MO_WT_WO['crontab'][$i]);
  205.                     if (3==count($ar)) {
  206.                         list($m, $wt, $wo) = $ar;
  207.                         $dayOffset=0;
  208.                     } elseif (4==count($ar)) {
  209.                         list($m, $wt, $wo, $dayOffset) = $ar;
  210.                     }
  211.                     unset ($ar);
  212.                     if ( 'string' == gettype($wo) ) { $wo = strtoupper( trim($wo) ); }
  213.                     if ( 'F' == $wo or 'FIRST' == $wo ) {
  214.                         $wo = 1;
  215.                     }
  216.                     $wt = $this -> wdnameToValue($wt);
  217.                     if ( 0 == intval($wt) ) { $wt = 7; }
  218.                     $wt = 7 - $wt;
  219.                     if ('L' == $wo or 'LAST' == $wo) {
  220.                         $daysOfMonth  = date( 't', mktime(0,0,0, $m, 1, $jahr) );
  221.                         $wdOffset = date( 'w', mktime(0,0,0, $m, $daysOfMonth, $jahr) );
  222.                         $time = mktime(0,0,0, $m, $daysOfMonth - $wdOffset + $dayOffset, $jahr);
  223.                         $d = date('j', $time);
  224.                         $m = date('n', $time);
  225.                     } else {
  226.                         $wdOffset = date('w', mktime(0,0,0, $m, $wt, $jahr));
  227.                         $datum = mktime(0,0,0, $m, ( - $offset + ($wo * 7)),$jahr );
  228.                         $time = mktime(0,0,0, $m, ( $wo * 7  - $wdOffset )  + $dayOffset, $jahr);
  229.                         $d = date('j', $time );
  230.                         $m = date('n', $time );
  231.                     }
  232.                     $name = $MO_WT_WO['name'][$i];
  233.                     $arCodes=array();
  234.                     if ( isset( $MO_WT_WO['codes'][$i] ) ) {
  235.                         $codes = preg_replace('/[^A-Za-z0-9_]+/' , ',' ,$MO_WT_WO['codes'][$i]);
  236.                         $arCodes = explode( ',', $codes ) ;
  237.                     }
  238.                     $this -> addFeiertag (intval($m), intval($d), $name, $arCodes);
  239.                 }
  240.             }
  241.             $Anniversaries = $ini['Anniversaries'];
  242.             $leer=array();
  243.             for ( $i = 0; $i < count($Anniversaries['y']); $i++ ) {
  244.                 $name = sprintf( $Anniversaries['s'][$i], $jahr - $Anniversaries['y'][$i], $Anniversaries['y'][$i], $Anniversaries['m'][$i], $Anniversaries['d'][$i]);
  245.                 $this -> addFeiertag ( intval($Anniversaries['m'][$i]), intval($Anniversaries['d'][$i]), $name, $leer);
  246.             }
  247.  
  248.  
  249.             $periodics = $ini['OtherPeriods'];
  250.             $leer = array();
  251.             for ( $i = 0; $i < count($periodics['name']); $i++ ) {
  252.                 $flag = true;
  253.                 $startDate   = mktime( 0,0,0, $periodics['FirstDay'][$i], $periodics['FirstMounth'][$i], $periodics['FirstYear'][$i] );
  254.                 if ( $periodics['FirstYear'][$i] == $jahr) {
  255.                     $this -> addFeiertag (date('m', $startDate), date('j', $startDate), $periodics['name'][$i], $leer);
  256.                 }
  257.                 if ( $periodics['FirstYear'][$i] <= $jahr) {
  258.                     while ($flag) {
  259.                         $startDate = mktime(0,0,0, date('m', $startDate) + $periodics['PeriodMounths'][$i], date('j', $startDate) + $periodics['PeriodDays'][$i], date('Y', $startDate) );
  260.                         if ( date('Y', $startDate) == $jahr) {
  261.                             $this -> addFeiertag (date('m', $startDate), date('j', $startDate), $periodics['name'][$i], $leer);
  262.                         } elseif ( date('Y', $startDate) > $jahr) {
  263.                             $flag = false;
  264.                         }
  265.                     }
  266.                 }
  267.             }
  268.             $this -> codes = $ini['codes'];
  269.             $export = '<?php
  270. $this -> feiertage = '.preg_replace('/\s+/', ' ', var_export( $this -> feiertage, true ) ) . ';
  271. $this -> codes = '.preg_replace('/\s+/', ' ', var_export( $this -> codes, true ) ) . ';';
  272.             file_put_contents($this -> cacheFile,$export);
  273.             return true;
  274.         } else {
  275.             $this -> jahr = $jahr;
  276.             require($this -> cacheFile);
  277.         }
  278.     }
  279.  
  280.     public function getJahr() {
  281.         return $this -> jahr;
  282.     }
  283.  
  284.     public function getDescriptionPerMD ( $m, $d ) {
  285.         $aRet=array();
  286.         $m = intval( $m );
  287.         $d = intval( $d );
  288.         try {
  289.             if ( ! checkdate( $m , $d , $this -> jahr ) ) {
  290.                 throw new Exception( 'Das übergebene Datum ' . $d . '.' . $m . '.' . $this -> jahr . ' ist ungültig.' );
  291.                 return false;
  292.  
  293.             }
  294.         } catch ( Exception $e ) {
  295.             echo 'Notiz: ',  $e->getMessage(), ' Datei: ' , $e->getFile(), ' Zeile: ', $e->getLine(), "\n";
  296.         }
  297.         $arReturns = array();
  298.         if ( isset( $this -> feiertage[$m][$d] ) ) {
  299.             if ( false == $this -> arrShowOnlyTypes ) {
  300.                 foreach( $this -> feiertage[$m][$d] as $found) {
  301.                     $aRet = array();
  302.                     $aRet['name'] = $found['name'];
  303.                     $aRet['codes'] = $found['codes'];
  304.                     $arReturns[] = $aRet;
  305.                 }
  306.             } else {
  307.                 foreach( $this -> feiertage[$m][$d] as $found) {
  308.                 #print_r($found);
  309.                    foreach ( $this -> arrShowOnlyTypes as $mustHave ) {
  310.                         #echo ' $mustHave: ', $mustHave, "\n";
  311.                        if ( $found['codes'] && in_array( $mustHave, $found['codes'] ) ) {
  312.                             $aRet = array();
  313.                             $aRet['name']  = $found['name'];
  314.                             $aRet['codes'] = $found['codes'];
  315.                             $arReturns[] = $aRet;
  316.                             break;
  317.                         }
  318.                     }
  319.                 }
  320.             }
  321.         }
  322.         if ( count ($arReturns) ) {
  323.             return $arReturns;
  324.         }
  325.     }
  326.  
  327.     public function setArrShowOnlyTypes ($var) {
  328.         $this -> arrShowOnlyTypes = array();
  329.         if (  'array' != gettype($var) ) {
  330.             $var = preg_replace('/[^A-Za-z0-9_]+/' , ',' , $var);
  331.             $var = explode( ',', $var );
  332.         }
  333.         $arr2 = array();
  334.         foreach ($var as $s) {
  335.             if ( '*' == $s ) {
  336.                 $this -> arrShowOnlyTypes = false;
  337.                 return true;
  338.             } else {
  339.                 if ('' != $s) {
  340.                     $arr2[] = strtoupper(trim($s));
  341.                 }
  342.             }
  343.         }
  344.         if (count ($arr2) ) {
  345.             $this -> arrShowOnlyTypes = $arr2;
  346.         } else {
  347.             $this -> arrShowOnlyTypes = false;
  348.         }
  349.     }
  350.  
  351.     public function getArrShowOnlyTypes () {
  352.         return $this -> arrShowOnlyTypes;
  353.     }
  354.  
  355.     private function addFeiertag ($m, $d, $name, $arCodes ) {
  356.         $arCodes2 = array();
  357.         foreach ($arCodes as $s) {
  358.             $s = trim($s);
  359.             if ($s) {
  360.                 $arCodes2[]=$s;
  361.             }
  362.         }
  363.         $ar['codes']= $arCodes2;
  364.         $ar['name'] = $name;
  365.         $this -> feiertage[ intval($m)][intval($d)][] = $ar;
  366.         return true;
  367.     }
  368.  
  369.     public function getDescriptionPerDTO ( $dto ) {
  370.         $d = date( 'j', $dto );
  371.         $m = date( 'n', $dto );
  372.         $y = date( 'Y', $dto );
  373.         return $this -> getDescriptionPerMD ( $m, $d, $y );
  374.     }
  375.  
  376.     public function isFeiertagPerDTO ( $dto, $mustHave ) {
  377.         $d = date( 'j', $dto );
  378.         $m = date( 'n', $dto );
  379.         $y = date( 'Y', $dto );
  380.  
  381.         try {
  382.             if ( ! checkdate( $m , $d , $this -> jahr ) ) {
  383.                 throw new Exception( 'Das übergebene Datum ' . $d . '.' . $m . '.' . $this -> jahr . ' ist ungültig.' );
  384.                 return false;
  385.             }
  386.         } catch ( Exception $e ) {
  387.             echo 'Notiz: ',  $e->getMessage(), ' Datei: ' , $e->getFile(), ' Zeile: ', $e->getLine(), "\n";
  388.         }
  389.  
  390.         return $this -> isFeiertagPerMD( $mustHave, $m, $d, $y );
  391.     }
  392.  
  393.     public function isFeiertagPerMD($m, $d, $y=false ) {
  394.  
  395.         $m = intval($m);
  396.         $d = intval($d);
  397.  
  398.         if ( $y !== false ) {
  399.             $y = intval($y);
  400.             if ( $y != $this -> jahr )  {
  401.                 $this -> setJahr( intval( $y ) );
  402.             }
  403.         }
  404.  
  405.         if ( isset( $this -> feiertage[$m][$d] ) ) {
  406.             if ( false == $this -> arrShowOnlyTypes ) {
  407.                 foreach ( $this -> feiertage[$m][$d] as $found ) {
  408.                     return $found['name'];
  409.                 }
  410.             } else {
  411.                 foreach ( $this -> feiertage[$m][$d] as $found ) {
  412.                     foreach ( $this -> arrShowOnlyTypes as $mustHave ) {
  413.                         if ( $found['codes'] && in_array( $mustHave, $found['codes'] )  ) {
  414.                             return  $found['name'];
  415.                         }
  416.                     }
  417.                 }
  418.             }
  419.         }
  420.         return false;
  421.     }
  422.  
  423.     public function getWdName ($wd) {
  424.         if ( isset($this -> wdNames[$wd]) ) {
  425.             return $this -> wdNames[$wd];
  426.         } else {
  427.             error_log(__FILE__ . 'function: getWdName('.$wd.') - ungültiger Parameter');
  428.         }
  429.     }
  430.  
  431.     public function getMonthName ($d, $start=1) {
  432.         $ds = $d - $start;
  433.         if ( isset($this -> monthNames[$ds]) ) {
  434.             return $this -> monthNames[$ds];
  435.         } else {
  436.             error_log(__FILE__ . 'function: getMonthName('.$d.','.$start.') - ungültiger Parameter' );
  437.         }
  438.     }
  439.  
  440.     public function countKalendarItems () {
  441.         $c=0;
  442.         foreach ($this -> feiertage as $day) {
  443.             foreach ($day as $ereignisse) {
  444.                 foreach($ereignisse as $ereignis) {
  445.                     if (! count( $ereignis['codes'] ) ) {
  446.                         $c++;
  447.                     } else {
  448.                         $c = $c + count($ereignis['codes']);
  449.                     }
  450.                 }
  451.             }
  452.         }
  453.         return $c;
  454.     }
  455.  
  456. }
  457.  
  458. // constants define for hhvm
  459. if(!defined('CAL_EASTER_DEFAULT')){
  460.     define('CAL_EASTER_DEFAULT',0);
  461. }
  462. if(!defined("CAL_EASTER_ROMAN")){
  463.     define('CAL_EASTER_ROMAN',1);
  464. }
  465. if(!defined('CAL_EASTER_ALWAYS_GREGORIAN')){
  466.     define('CAL_EASTER_ALWAYS_GREGORIAN',2);
  467. }
  468. if(!defined('CAL_EASTER_ALWAYS_JULIAN')){
  469.     define('CAL_EASTER_ALWAYS_JULIAN',3);
  470. }
  471.  
  472. if (! function_exists( 'easter_days' ) ) {
  473.  
  474.     /**
  475.     *    code by rabbit-aaron, https://github.com/rabbit-aaron
  476.     *    based on code by Simon Kershaw, <webmaster@ely.anglican.org>
  477.     *    License: https://github.com/rabbit-aaron/hhvm-php-easter/blob/master/LICENSE
  478.     **/
  479.  
  480.     function easter_days( $year = NULL, $method = CAL_EASTER_DEFAULT )  {
  481.  
  482.         /**
  483.             gibt den offset (in Tagen) zum 21.3. zurück.
  484.         **/
  485.  
  486.         if( $year == NULL ) {
  487.             $year = intval( date( 'Y' ) );
  488.         }
  489.         $golden = ( $year % 19 ) + 1;
  490.         if ( ( $year <= 1582 && $method != CAL_EASTER_ALWAYS_GREGORIAN ) ||
  491.             ( $year >= 1583 && $year <= 1752 && $method != CAL_EASTER_ROMAN && $method != CAL_EASTER_ALWAYS_GREGORIAN ) ||
  492.             $method == CAL_EASTER_ALWAYS_JULIAN ) {
  493.  
  494.             $dom = ( $year + (int)($year/4) + 5) % 7;
  495.             if ( $dom < 0 ) {
  496.                 $dom += 7;
  497.             }
  498.             $pfm = ( 3 - ( 11 * $golden ) - 7 ) % 30;
  499.             if ($pfm < 0) {
  500.                 $pfm += 30;
  501.             }
  502.         } else {
  503.             $dom = ( $year + (int)( $year / 4 ) - (int)( $year / 100 ) + (int)( $year / 400 ) ) % 7;
  504.             if ( $dom < 0 ) {
  505.                 $dom += 7;
  506.             }
  507.             $solar = (int)( ( $year - 1600 ) / 100 ) - (int)( ( $year - 1600 ) / 400) ;
  508.             $lunar = (int)( ( ( (int)( ($year - 1400 ) / 100 ) ) * 8 ) / 25 );
  509.             $pfm = ( 3 - ( 11 * $golden ) + $solar - $lunar ) % 30;
  510.             if ( $pfm < 0 ) {
  511.                 $pfm += 30;
  512.             }
  513.         }
  514.         if ( ( $pfm == 29 ) || ( $pfm == 28 && $golden > 11 ) ) {
  515.             $pfm--;
  516.         }
  517.         $tmp = ( 4 - $pfm - $dom ) % 7;
  518.         if ( $tmp < 0 ) {
  519.             $tmp += 7;
  520.         }
  521.         $easter = $pfm + $tmp + 1;               /* Easter as the number of days after 21st March */
  522.         return $easter;
  523.     }
  524. }