Skip to content

Commit 8ef0e4c

Browse files
authored
Allow easter_date to process years after 2037 on 64bit systems (#11862)
Added a check to easter_date to allow it to run with years past 2037 when on a 64bit platform.
1 parent e5b2590 commit 8ef0e4c

6 files changed

+105
-2
lines changed

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,10 @@ PHP 8.3 UPGRADE NOTES
317317
significant digits before the decimal point. Previously negative $decimals
318318
got silently ignored and the number got rounded to zero decimal places.
319319

320+
- Calendar
321+
. easter_date() now supports years from 1970 to 2,000,000,000 on 64-bit systems,
322+
previously it only supported years in the range from 1970 to 2037.
323+
320324
========================================
321325
6. New Functions
322326
========================================

ext/calendar/easter.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
| Authors: Shane Caraveo <[email protected]> |
1414
| Colin Viebrock <[email protected]> |
1515
| Hartmut Holzgraefe <[email protected]> |
16+
| Arne Perschke <[email protected]> |
1617
+----------------------------------------------------------------------+
1718
*/
1819

@@ -21,6 +22,10 @@
2122
#include "sdncal.h"
2223
#include <time.h>
2324

25+
/**
26+
* If `gm` is true this will return the timestamp at midnight on Easter of the given year. If it is false this
27+
* will return the number of days Easter is after March 21st.
28+
*/
2429
static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm)
2530
{
2631
/* based on code by Simon Kershaw, <[email protected]> */
@@ -48,10 +53,27 @@ static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm)
4853
}
4954
}
5055

51-
if (gm && (year<1970 || year>2037)) { /* out of range for timestamps */
56+
#ifdef ZEND_ENABLE_ZVAL_LONG64
57+
/* Compiling for 64bit, allow years between 1970 and 2.000.000.000 */
58+
if (gm && year < 1970) {
59+
/* timestamps only start after 1970 */
60+
zend_argument_value_error(1, "must be a year after 1970 (inclusive)");
61+
RETURN_THROWS();
62+
}
63+
64+
if (gm && year > 2000000000) {
65+
/* timestamps only go up to the year 2.000.000.000 */
66+
zend_argument_value_error(1, "must be a year before 2.000.000.000 (inclusive)");
67+
RETURN_THROWS();
68+
}
69+
#else
70+
/* Compiling for 32bit, allow years between 1970 and 2037 */
71+
if (gm && (year < 1970 || year > 2037)) {
5272
zend_argument_value_error(1, "must be between 1970 and 2037 (inclusive)");
5373
RETURN_THROWS();
5474
}
75+
#endif
76+
5577

5678
golden = (year % 19) + 1; /* the Golden number */
5779

ext/calendar/tests/easter_date.phpt renamed to ext/calendar/tests/easter_date_32bit.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
--TEST--
2-
easter_date()
2+
Test easter_date() on 32bit systems
3+
--SKIPIF--
4+
<?php if (PHP_INT_SIZE != 4) die("skip 32-bit only"); ?>
35
--INI--
46
date.timezone=UTC
57
--ENV--
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Test easter_date() on 64bit systems
3+
--SKIPIF--
4+
<?php if (PHP_INT_SIZE != 8) die("skip 64-bit only"); ?>
5+
--INI--
6+
date.timezone=UTC
7+
--ENV--
8+
TZ=UTC
9+
--EXTENSIONS--
10+
calendar
11+
--FILE--
12+
<?php
13+
putenv('TZ=UTC');
14+
echo date("Y-m-d", easter_date(2000))."\n";
15+
echo date("Y-m-d", easter_date(2001))."\n";
16+
echo date("Y-m-d", easter_date(2002))."\n";
17+
echo date("Y-m-d", easter_date(2045))."\n";
18+
echo date("Y-m-d", easter_date(2046))."\n";
19+
echo date("Y-m-d", easter_date(2047))."\n";
20+
try {
21+
easter_date(1492);
22+
} catch (ValueError $ex) {
23+
echo "{$ex->getMessage()}\n";
24+
}
25+
?>
26+
--EXPECT--
27+
2000-04-23
28+
2001-04-15
29+
2002-03-31
30+
2045-04-09
31+
2046-03-25
32+
2047-04-14
33+
easter_date(): Argument #1 ($year) must be a year after 1970 (inclusive)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Test easter_date() on 32bit systems checks the upper year limit
3+
--SKIPIF--
4+
<?php if (PHP_INT_SIZE != 4) die("skip 32-bit only"); ?>
5+
--INI--
6+
date.timezone=UTC
7+
--ENV--
8+
TZ=UTC
9+
--EXTENSIONS--
10+
calendar
11+
--FILE--
12+
<?php
13+
putenv('TZ=UTC');
14+
try {
15+
easter_date(2040);
16+
} catch (ValueError $ex) {
17+
echo "{$ex->getMessage()}\n";
18+
}
19+
?>
20+
--EXPECT--
21+
easter_date(): Argument #1 ($year) must be between 1970 and 2037 (inclusive)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Test easter_date() on 64bit systems checks the upper year limit
3+
--SKIPIF--
4+
<?php if (PHP_INT_SIZE != 8) die("skip 64-bit only"); ?>
5+
--INI--
6+
date.timezone=UTC
7+
--ENV--
8+
TZ=UTC
9+
--EXTENSIONS--
10+
calendar
11+
--FILE--
12+
<?php
13+
putenv('TZ=UTC');
14+
try {
15+
easter_date(293274701009);
16+
} catch (ValueError $ex) {
17+
echo "{$ex->getMessage()}\n";
18+
}
19+
?>
20+
--EXPECT--
21+
easter_date(): Argument #1 ($year) must be a year before 2.000.000.000 (inclusive)

0 commit comments

Comments
 (0)