root/ext/calendar/easter.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _cal_easter
  2. PHP_FUNCTION
  3. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Shane Caraveo             <shane@caraveo.com>               | 
  16    |          Colin Viebrock            <colin@easydns.com>               |
  17    |          Hartmut Holzgraefe        <hholzgra@php.net>                |
  18    +----------------------------------------------------------------------+
  19  */
  20 /* $Id: */
  21 
  22 #include "php.h"
  23 #include "php_calendar.h"
  24 #include "sdncal.h"
  25 #include <time.h>
  26 
  27 static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, int gm)
  28 {
  29 
  30         /* based on code by Simon Kershaw, <webmaster@ely.anglican.org> */
  31 
  32         struct tm te;
  33         long year, golden, solar, lunar, pfm, dom, tmp, easter;
  34         long method = CAL_EASTER_DEFAULT;
  35 
  36         /* Default to the current year if year parameter is not given */
  37         {
  38                 time_t a;
  39                 struct tm b, *res;
  40                 time(&a);
  41                 res = php_localtime_r(&a, &b);
  42                 if (!res) {
  43                         year = 1900;
  44                 } else {
  45                         year = 1900 + b.tm_year;
  46                 }
  47         }
  48 
  49         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
  50                 "|ll", &year, &method) == FAILURE) {
  51                         return;
  52         }
  53  
  54         if (gm && (year<1970 || year>2037)) {                           /* out of range for timestamps */
  55                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "This function is only valid for years between 1970 and 2037 inclusive");
  56                 RETURN_FALSE;
  57         }
  58 
  59         golden = (year % 19) + 1;                                       /* the Golden number */
  60 
  61         if ((year <= 1582 && method != CAL_EASTER_ALWAYS_GREGORIAN) ||
  62             (year >= 1583 && year <= 1752 && method != CAL_EASTER_ROMAN && method != CAL_EASTER_ALWAYS_GREGORIAN) ||
  63              method == CAL_EASTER_ALWAYS_JULIAN) {              /* JULIAN CALENDAR */
  64              
  65                 dom = (year + (year/4) + 5) % 7;                        /* the "Dominical number" - finding a Sunday */
  66                 if (dom < 0) {
  67                         dom += 7;
  68                 }
  69 
  70                 pfm = (3 - (11*golden) - 7) % 30;                       /* uncorrected date of the Paschal full moon */
  71                 if (pfm < 0) {
  72                         pfm += 30;
  73                 }
  74         } else {                                                        /* GREGORIAN CALENDAR */
  75                 dom = (year + (year/4) - (year/100) + (year/400)) % 7;  /* the "Domincal number" */
  76                 if (dom < 0) {
  77                         dom += 7;
  78                 }
  79 
  80                 solar = (year-1600)/100 - (year-1600)/400;              /* the solar and lunar corrections */
  81                 lunar = (((year-1400) / 100) * 8) / 25;
  82 
  83                 pfm = (3 - (11*golden) + solar - lunar) % 30;           /* uncorrected date of the Paschal full moon */
  84                 if (pfm < 0) {
  85                         pfm += 30;
  86                 }
  87         }
  88 
  89         if ((pfm == 29) || (pfm == 28 && golden > 11)) {                /* corrected date of the Paschal full moon */
  90                 pfm--;                                                  /* - days after 21st March                 */
  91         }
  92 
  93         tmp = (4-pfm-dom) % 7;
  94         if (tmp < 0) {
  95                 tmp += 7;
  96         }
  97 
  98         easter = pfm + tmp + 1;                                         /* Easter as the number of days after 21st March */
  99 
 100         if (gm) {                                                       /* return a timestamp */
 101                 te.tm_isdst = -1;
 102                 te.tm_year = year-1900;
 103                 te.tm_sec = 0;
 104                 te.tm_min = 0;
 105                 te.tm_hour = 0;
 106 
 107                 if (easter < 11) {
 108                         te.tm_mon = 2;                  /* March */
 109                         te.tm_mday = easter+21;
 110                 } else {
 111                         te.tm_mon = 3;                  /* April */
 112                         te.tm_mday = easter-10;
 113                 }
 114 
 115                 Z_LVAL_P(return_value) = mktime(&te);
 116         } else {                                                        /* return the days after March 21 */    
 117                 Z_LVAL_P(return_value) = easter;
 118         }
 119 
 120         Z_TYPE_P(return_value) = IS_LONG;
 121 
 122 }
 123 
 124 /* {{{ proto int easter_date([int year])
 125    Return the timestamp of midnight on Easter of a given year (defaults to current year) */
 126 PHP_FUNCTION(easter_date)
 127 {
 128         _cal_easter(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
 129 }
 130 /* }}} */
 131 
 132 /* {{{ proto int easter_days([int year, [int method]])
 133    Return the number of days after March 21 that Easter falls on for a given year (defaults to current year) */
 134 PHP_FUNCTION(easter_days)
 135 {
 136         _cal_easter(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
 137 }
 138 /* }}} */
 139 
 140 /*
 141  * Local variables:
 142  * tab-width: 4
 143  * c-basic-offset: 4
 144  * End:
 145  */

/* [<][>][^][v][top][bottom][index][help] */