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 7                                                        |
   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, zend_long gm)
  28 {
  29 
  30         /* based on code by Simon Kershaw, <webmaster@ely.anglican.org> */
  31 
  32         struct tm te;
  33         zend_long year, golden, solar, lunar, pfm, dom, tmp, easter, result;
  34         zend_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(),
  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, 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             result = mktime(&te);
 115         } else {                                                        /* return the days after March 21 */
 116             result = easter;
 117         }
 118     ZVAL_LONG(return_value, result);
 119 }
 120 
 121 /* {{{ proto int easter_date([int year])
 122    Return the timestamp of midnight on Easter of a given year (defaults to current year) */
 123 PHP_FUNCTION(easter_date)
 124 {
 125         _cal_easter(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
 126 }
 127 /* }}} */
 128 
 129 /* {{{ proto int easter_days([int year, [int method]])
 130    Return the number of days after March 21 that Easter falls on for a given year (defaults to current year) */
 131 PHP_FUNCTION(easter_days)
 132 {
 133         _cal_easter(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
 134 }
 135 /* }}} */
 136 
 137 /*
 138  * Local variables:
 139  * tab-width: 4
 140  * c-basic-offset: 4
 141  * End:
 142  */

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