Back to index

php5  5.3.10
easter.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Shane Caraveo             <shane@caraveo.com>               | 
00016    |          Colin Viebrock            <colin@easydns.com>               |
00017    |          Hartmut Holzgraefe        <hholzgra@php.net>                |
00018    +----------------------------------------------------------------------+
00019  */
00020 /* $Id: */
00021 
00022 #include "php.h"
00023 #include "php_calendar.h"
00024 #include "sdncal.h"
00025 #include <time.h>
00026 
00027 static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, int gm)
00028 {
00029 
00030        /* based on code by Simon Kershaw, <webmaster@ely.anglican.org> */
00031 
00032        struct tm te;
00033        long year, golden, solar, lunar, pfm, dom, tmp, easter;
00034        long method = CAL_EASTER_DEFAULT;
00035 
00036        /* Default to the current year if year parameter is not given */
00037        {
00038               time_t a;
00039               struct tm b, *res;
00040               time(&a);
00041               res = php_localtime_r(&a, &b);
00042               if (!res) {
00043                      year = 1900;
00044               } else {
00045                      year = 1900 + b.tm_year;
00046               }
00047        }
00048 
00049        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
00050               "|ll", &year, &method) == FAILURE) {
00051                      return;
00052        }
00053  
00054        if (gm && (year<1970 || year>2037)) {                          /* out of range for timestamps */
00055               php_error_docref(NULL TSRMLS_CC, E_WARNING, "This function is only valid for years between 1970 and 2037 inclusive");
00056               RETURN_FALSE;
00057        }
00058 
00059        golden = (year % 19) + 1;                               /* the Golden number */
00060 
00061        if ((year <= 1582 && method != CAL_EASTER_ALWAYS_GREGORIAN) ||
00062            (year >= 1583 && year <= 1752 && method != CAL_EASTER_ROMAN && method != CAL_EASTER_ALWAYS_GREGORIAN) ||
00063             method == CAL_EASTER_ALWAYS_JULIAN) {              /* JULIAN CALENDAR */
00064             
00065               dom = (year + (year/4) + 5) % 7;                 /* the "Dominical number" - finding a Sunday */
00066               if (dom < 0) {
00067                      dom += 7;
00068               }
00069 
00070               pfm = (3 - (11*golden) - 7) % 30;                /* uncorrected date of the Paschal full moon */
00071               if (pfm < 0) {
00072                      pfm += 30;
00073               }
00074        } else {                                                /* GREGORIAN CALENDAR */
00075               dom = (year + (year/4) - (year/100) + (year/400)) % 7;  /* the "Domincal number" */
00076               if (dom < 0) {
00077                      dom += 7;
00078               }
00079 
00080               solar = (year-1600)/100 - (year-1600)/400;              /* the solar and lunar corrections */
00081               lunar = (((year-1400) / 100) * 8) / 25;
00082 
00083               pfm = (3 - (11*golden) + solar - lunar) % 30;           /* uncorrected date of the Paschal full moon */
00084               if (pfm < 0) {
00085                      pfm += 30;
00086               }
00087        }
00088 
00089        if ((pfm == 29) || (pfm == 28 && golden > 11)) {        /* corrected date of the Paschal full moon */
00090               pfm--;                                           /* - days after 21st March                 */
00091        }
00092 
00093        tmp = (4-pfm-dom) % 7;
00094        if (tmp < 0) {
00095               tmp += 7;
00096        }
00097 
00098        easter = pfm + tmp + 1;                                        /* Easter as the number of days after 21st March */
00099 
00100        if (gm) {                                               /* return a timestamp */
00101               te.tm_isdst = -1;
00102               te.tm_year = year-1900;
00103               te.tm_sec = 0;
00104               te.tm_min = 0;
00105               te.tm_hour = 0;
00106 
00107               if (easter < 11) {
00108                      te.tm_mon = 2;                     /* March */
00109                      te.tm_mday = easter+21;
00110               } else {
00111                      te.tm_mon = 3;                     /* April */
00112                      te.tm_mday = easter-10;
00113               }
00114 
00115                Z_LVAL_P(return_value) = mktime(&te);
00116        } else {                                                /* return the days after March 21 */      
00117                Z_LVAL_P(return_value) = easter;
00118        }
00119 
00120         Z_TYPE_P(return_value) = IS_LONG;
00121 
00122 }
00123 
00124 /* {{{ proto int easter_date([int year])
00125    Return the timestamp of midnight on Easter of a given year (defaults to current year) */
00126 PHP_FUNCTION(easter_date)
00127 {
00128        _cal_easter(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
00129 }
00130 /* }}} */
00131 
00132 /* {{{ proto int easter_days([int year, [int method]])
00133    Return the number of days after March 21 that Easter falls on for a given year (defaults to current year) */
00134 PHP_FUNCTION(easter_days)
00135 {
00136        _cal_easter(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
00137 }
00138 /* }}} */
00139 
00140 /*
00141  * Local variables:
00142  * tab-width: 4
00143  * c-basic-offset: 4
00144  * End:
00145  */