From a7079735236492ddbc575a7adcd4d512ca11ffe4 Mon Sep 17 00:00:00 2001 From: mateuszz0000 Date: Mon, 18 May 2020 14:41:06 +0200 Subject: [PATCH 1/3] Added gauss easter algorithm --- other/gauss_easter.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 other/gauss_easter.py diff --git a/other/gauss_easter.py b/other/gauss_easter.py new file mode 100644 index 000000000000..e0a5037a77e0 --- /dev/null +++ b/other/gauss_easter.py @@ -0,0 +1,43 @@ +""" +https://en.wikipedia.org/wiki/Computus#Gauss'_Easter_algorithm +""" +from datetime import datetime, timedelta + + +def gauss_easter(year: int) -> datetime: + """ + Calculation Gregorian easter date for given year + + >>> gauss_easter(2007) + datetime.datetime(2007, 4, 8, 0, 0) + + >>> gauss_easter(2008) + datetime.datetime(2008, 3, 23, 0, 0) + + >>> gauss_easter(2020) + datetime.datetime(2020, 4, 12, 0, 0) + + >>> gauss_easter(2021) + datetime.datetime(2021, 4, 4, 0, 0) + """ + a = year % 19 + b = year % 4 + c = year % 7 + k = year // 100 + p = (13 + 8 * k) / 25 + q = k / 4 + M = (15 - p + k - q) % 30 + N = (4 + k - q) % 7 + d = (19 * a + M) % 30 + e = (2 * b + 4 * c + 6 * d + N) % 7 + + if d == 29 and e == 6: + return datetime(year, 4, 19) + elif d == 28 and e == 6: + return datetime(year, 4, 18) + else: + print(22, 22 + d + e, d + e) + return datetime(year, 3, 22) + timedelta(days=int(d + e)) + +if __name__ == '__main__': + print(gauss_easter(2021)) \ No newline at end of file From c79682b0271730e8238f4d47106865ae4e93175f Mon Sep 17 00:00:00 2001 From: mateuszz0000 Date: Tue, 19 May 2020 08:24:34 +0200 Subject: [PATCH 2/3] Fixes in easter algorithm --- other/gauss_easter.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/other/gauss_easter.py b/other/gauss_easter.py index e0a5037a77e0..58452544382e 100644 --- a/other/gauss_easter.py +++ b/other/gauss_easter.py @@ -1,6 +1,7 @@ """ https://en.wikipedia.org/wiki/Computus#Gauss'_Easter_algorithm """ +import math from datetime import datetime, timedelta @@ -23,8 +24,8 @@ def gauss_easter(year: int) -> datetime: a = year % 19 b = year % 4 c = year % 7 - k = year // 100 - p = (13 + 8 * k) / 25 + k = math.floor(year / 100) + p = math.floor((13 + 8 * k) / 25) q = k / 4 M = (15 - p + k - q) % 30 N = (4 + k - q) % 7 @@ -36,8 +37,12 @@ def gauss_easter(year: int) -> datetime: elif d == 28 and e == 6: return datetime(year, 4, 18) else: - print(22, 22 + d + e, d + e) return datetime(year, 3, 22) + timedelta(days=int(d + e)) + if __name__ == '__main__': - print(gauss_easter(2021)) \ No newline at end of file + print(f"Easter in 2023 will be {gauss_easter(2023)}") + print(f"Easter in 2021 will be {gauss_easter(2021)}") + print(f"Easter in 2010 was {gauss_easter(2010)}") + print(f"Easter in 1994 was {gauss_easter(1994)}") + print(f"Easter in 2000 was {gauss_easter(2000)}") From 46a374874fe9db0ce9f568dc24d9fc5e9adc7d30 Mon Sep 17 00:00:00 2001 From: mateuszz0000 Date: Tue, 19 May 2020 13:28:37 +0200 Subject: [PATCH 3/3] Commit suggestions --- other/gauss_easter.py | 51 ++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/other/gauss_easter.py b/other/gauss_easter.py index 58452544382e..4447d4ab86af 100644 --- a/other/gauss_easter.py +++ b/other/gauss_easter.py @@ -21,28 +21,39 @@ def gauss_easter(year: int) -> datetime: >>> gauss_easter(2021) datetime.datetime(2021, 4, 4, 0, 0) """ - a = year % 19 - b = year % 4 - c = year % 7 - k = math.floor(year / 100) - p = math.floor((13 + 8 * k) / 25) - q = k / 4 - M = (15 - p + k - q) % 30 - N = (4 + k - q) % 7 - d = (19 * a + M) % 30 - e = (2 * b + 4 * c + 6 * d + N) % 7 - - if d == 29 and e == 6: + metonic_cycle = year % 19 + julian_leap_year = year % 4 + non_leap_year = year % 7 + leap_day_inhibits = math.floor(year / 100) + lunar_orbit_correction = math.floor((13 + 8 * leap_day_inhibits) / 25) + leap_day_reinstall_number = leap_day_inhibits / 4 + secular_moon_shift = ( + 15 - lunar_orbit_correction + leap_day_inhibits - leap_day_reinstall_number + ) % 30 + century_starting_point = (4 + leap_day_inhibits - leap_day_reinstall_number) % 7 + + # days to be added to March 21 + days_to_add = (19 * metonic_cycle + secular_moon_shift) % 30 + + # PHM -> Paschal Full Moon + days_from_phm_to_sunday = ( + 2 * julian_leap_year + + 4 * non_leap_year + + 6 * days_to_add + + century_starting_point + ) % 7 + + if days_to_add == 29 and days_from_phm_to_sunday == 6: return datetime(year, 4, 19) - elif d == 28 and e == 6: + elif days_to_add == 28 and days_from_phm_to_sunday == 6: return datetime(year, 4, 18) else: - return datetime(year, 3, 22) + timedelta(days=int(d + e)) + return datetime(year, 3, 22) + timedelta( + days=int(days_to_add + days_from_phm_to_sunday) + ) -if __name__ == '__main__': - print(f"Easter in 2023 will be {gauss_easter(2023)}") - print(f"Easter in 2021 will be {gauss_easter(2021)}") - print(f"Easter in 2010 was {gauss_easter(2010)}") - print(f"Easter in 1994 was {gauss_easter(1994)}") - print(f"Easter in 2000 was {gauss_easter(2000)}") +if __name__ == "__main__": + for year in (1994, 2000, 2010, 2021, 2023): + tense = "will be" if year > datetime.now().year else "was" + print(f"Easter in {year} {tense} {gauss_easter(year)}")