Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Easter date calculation error #324

Closed
rChassat opened this issue Nov 20, 2023 · 3 comments
Closed

Easter date calculation error #324

rChassat opened this issue Nov 20, 2023 · 3 comments
Labels

Comments

@rChassat
Copy link
Contributor

Hello I have done some testing on the easter date calcultation function from the ChristianHolidays.php, and I saw some incorrect date returned like for the 2025 year.
So I compared to the C solution from php-src calendar/easter.c and found out what caused the problem, so here is the function fixed :

    protected function calculateEaster(int $year, string $timezone): \DateTimeInterface
    {
        if (\extension_loaded('calendar')) {
            $easterDays = easter_days($year);
        } else {
            $golden = ($year % 19) + 1; // The Golden Number

            // The Julian calendar applies to the original method from 326AD. The Gregorian calendar was first
            // introduced in October 1582 in Italy. Easter algorithms using the Gregorian calendar apply to years
            // 1583 AD to 4099 (A day adjustment is required in or shortly after 4100 AD).
            // After 1752, most western churches have adopted the current algorithm.
            if ($year <= 1752) {
                $dom = ($year + (int) ($year / 4) + 5) % 7; // The 'Dominical number' - finding a Sunday
                if ($dom < 0) {
                    $dom += 7;
                }

                $pfm = (3 - (11 * $golden) - 7) % 30; // Uncorrected date of the Paschal full moon
            } else {
                $dom = ($year + (int) ($year / 4) - (int) ($year / 100) + (int) ($year / 400)) % 7; // The 'Dominical number' - finding a Sunday
                if ($dom < 0) {
                    $dom += 7;
                }

                $solar = (int) (($year - 1600) / 100) - (int) (($year - 1600) / 400); // The solar correction
                $lunar = (int) ((int) (($year - 1400) / 100) * 8 / 25); // The lunar correction

                $pfm = (3 - (11 * $golden) + $solar - $lunar) % 30; // Uncorrected date of the Paschal full moon
            }

            if ($pfm < 0) {
                $pfm += 30;
            }

            // Corrected date of the Paschal full moon, - days after 21st March
            if ((29 === $pfm) || (28 === $pfm && $golden > 11)) {
                --$pfm;
            }

            $tmp = (4 - $pfm - $dom) % 7;
            if ($tmp < 0) {
                $tmp += 7;
            }

            $easterDays = $pfm + $tmp + 1; // Easter as the number of days after 21st March
        }

        if ($easterDays < 11) {
            $easter = new \DateTime("{$year}-3-21");
            $easter->add(new \DateInterval('P' . $easterDays . 'D'));
        } else {
            $easterDays = $easterDays - 10;
            $easter = new \DateTime("{$year}-4-{$easterDays}");
        }

        return $easter;
    }

Basically I fixed the lunar calculation rounding and changed the ending calculation of the date based on the php-src code.

@stelgenhof
Copy link
Member

@rChasaat Thank you very much for reporting this. Could you create a PR including unit tests that resolve this error?

Cheers! Sacha

@rChassat
Copy link
Contributor Author

Yes here you go : #326

@stelgenhof
Copy link
Member

Resolved in #326

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants