php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
easter.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Shane Caraveo <shane@caraveo.com> |
14 | Colin Viebrock <colin@easydns.com> |
15 | Hartmut Holzgraefe <hholzgra@php.net> |
16 | Arne Perschke <a.perschke@hctec.net> |
17 +----------------------------------------------------------------------+
18 */
19
20#include "php.h"
21#include "php_calendar.h"
22#include "sdncal.h"
23#include <time.h>
24
29static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm)
30{
31 /* based on code by Simon Kershaw, <webmaster@ely.anglican.org> */
32
33 struct tm te;
34 zend_long year, golden, solar, lunar, pfm, dom, tmp, easter, result;
36 const zend_long max_year = (zend_long)(ZEND_LONG_MAX / 5) * 4;
37 bool year_is_null = 1;
38
40 "|l!l", &year, &year_is_null, &method) == FAILURE) {
42 }
43
44 /* Default to the current year if year parameter is not given */
45 if (year_is_null) {
46 time_t a;
47 struct tm b, *res;
48 time(&a);
49 res = php_localtime_r(&a, &b);
50 if (!res) {
51 year = 1900;
52 } else {
53 year = 1900 + b.tm_year;
54 }
55 }
56
57 if (year <= 0 || year > max_year) {
58 zend_argument_value_error(1, "must be between 1 and " ZEND_LONG_FMT, max_year);
60 }
61
62 #ifdef ZEND_ENABLE_ZVAL_LONG64
63 /* Compiling for 64bit, allow years between 1970 and 2.000.000.000 */
64 if (gm && year < 1970) {
65 /* timestamps only start after 1970 */
66 zend_argument_value_error(1, "must be a year after 1970 (inclusive)");
68 }
69
70 if (gm && year > 2000000000) {
71 /* timestamps only go up to the year 2.000.000.000 */
72 zend_argument_value_error(1, "must be a year before 2.000.000.000 (inclusive)");
74 }
75 #else
76 /* Compiling for 32bit, allow years between 1970 and 2037 */
77 if (gm && (year < 1970 || year > 2037)) {
78 zend_argument_value_error(1, "must be between 1970 and 2037 (inclusive)");
80 }
81 #endif
82
83
84 golden = (year % 19) + 1; /* the Golden number */
85
86 if ((year <= 1582 && method != CAL_EASTER_ALWAYS_GREGORIAN) ||
87 (year >= 1583 && year <= 1752 && method != CAL_EASTER_ROMAN && method != CAL_EASTER_ALWAYS_GREGORIAN) ||
88 method == CAL_EASTER_ALWAYS_JULIAN) { /* JULIAN CALENDAR */
89
90 dom = (year + (year/4) + 5) % 7; /* the "Dominical number" - finding a Sunday */
91 if (dom < 0) {
92 dom += 7;
93 }
94
95 pfm = (3 - (11*golden) - 7) % 30; /* uncorrected date of the Paschal full moon */
96 if (pfm < 0) {
97 pfm += 30;
98 }
99 } else { /* GREGORIAN CALENDAR */
100 dom = (year + (year/4) - (year/100) + (year/400)) % 7; /* the "Domincal number" */
101 if (dom < 0) {
102 dom += 7;
103 }
104
105 solar = (year-1600)/100 - (year-1600)/400; /* the solar and lunar corrections */
106 lunar = (((year-1400) / 100) * 8) / 25;
107
108 pfm = (3 - (11*golden) + solar - lunar) % 30; /* uncorrected date of the Paschal full moon */
109 if (pfm < 0) {
110 pfm += 30;
111 }
112 }
113
114 if ((pfm == 29) || (pfm == 28 && golden > 11)) { /* corrected date of the Paschal full moon */
115 pfm--; /* - days after 21st March */
116 }
117
118 tmp = (4-pfm-dom) % 7;
119 if (tmp < 0) {
120 tmp += 7;
121 }
122
123 easter = pfm + tmp + 1; /* Easter as the number of days after 21st March */
124
125 if (gm) { /* return a timestamp */
126 te.tm_isdst = -1;
127 te.tm_year = year-1900;
128 te.tm_sec = 0;
129 te.tm_min = 0;
130 te.tm_hour = 0;
131
132 if (easter < 11) {
133 te.tm_mon = 2; /* March */
134 te.tm_mday = easter+21;
135 } else {
136 te.tm_mon = 3; /* April */
137 te.tm_mday = easter-10;
138 }
139 result = mktime(&te);
140 } else { /* return the days after March 21 */
141 result = easter;
142 }
144}
145
146/* {{{ Return the timestamp of midnight on Easter of a given year (defaults to current year) */
151/* }}} */
152
153/* {{{ Return the number of days after March 21 that Easter falls on for a given year (defaults to current year) */
158/* }}} */
easter_days(?int $year=null, int $mode=CAL_EASTER_DEFAULT)
easter_date(?int $year=null, int $mode=CAL_EASTER_DEFAULT)
zend_string * res
Definition ffi.c:4692
#define PHP_FUNCTION
Definition php.h:364
#define CAL_EASTER_ALWAYS_GREGORIAN
#define CAL_EASTER_ROMAN
#define CAL_EASTER_DEFAULT
#define CAL_EASTER_ALWAYS_JULIAN
mktime(int $hour, ?int $minute=null, ?int $second=null, ?int $month=null, ?int $day=null, ?int $year=null)
time()
PHPAPI struct tm * php_localtime_r(const time_t *const timep, struct tm *p_tm)
Definition reentrancy.c:110
$obj a
Definition test.php:84
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_THROWS()
Definition zend_API.h:1060
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_FMT
Definition zend_long.h:87
#define ZEND_LONG_MAX
Definition zend_long.h:45
#define ZVAL_LONG(z, l)
@ FAILURE
Definition zend_types.h:61
zval * return_value
bool result