|
| 1 | +import strformat |
| 2 | + |
| 3 | +func computus(year: int, servois: bool = false): string = |
| 4 | + let |
| 5 | + # Year's position on the 19 year metonic cycle |
| 6 | + a = year mod 19 |
| 7 | + # Century index |
| 8 | + k = year div 100 |
| 9 | + # Shift of metonic cycle, add a day offset every 300 years |
| 10 | + p = (13 + 8 * k) div 25 |
| 11 | + # Correction for non-observed leap days |
| 12 | + q = k div 4 |
| 13 | + # Correction to starting point of calculation each century |
| 14 | + m = (15 - p + k - q) mod 30 |
| 15 | + # Number of days from March 21st until the full moon |
| 16 | + d = (19 * a + m) mod 30 |
| 17 | + # Returning of user wants value for Servois' table |
| 18 | + if servois: |
| 19 | + return $((21 + d) mod 31) |
| 20 | + let |
| 21 | + # Find the next Sunday |
| 22 | + # Century-based offset in weekly calculation |
| 23 | + n = (4 + k - q) mod 7 |
| 24 | + # Correction for leap days |
| 25 | + b = year mod 4 |
| 26 | + c = year mod 7 |
| 27 | + # Days from d to next Sunday |
| 28 | + temp_e = (2 * b + 4 * c + 6 * d + n) mod 7 |
| 29 | + # Historical corrections for April 26 and 25 |
| 30 | + e = if (d == 29 and temp_e == 6) or (d == 28 and temp_e == 6 and a > 10): |
| 31 | + -1 |
| 32 | + else: |
| 33 | + temp_e |
| 34 | + # Determination of the correct month for Easter |
| 35 | + if (22 + d + e) > 31: |
| 36 | + result = "April {d + e - 9}".fmt |
| 37 | + else: |
| 38 | + result = "March {22 + d + e}".fmt |
| 39 | + |
| 40 | +when isMainModule: |
| 41 | + echo "The following are the dates of the Paschal full moon (using Servois " |
| 42 | + echo "notation) and the date of Easter for 2020-2030 AD:" |
| 43 | + echo "Year Servois number Easter" |
| 44 | + for year in 2020..2030: |
| 45 | + echo "{year} {computus(year, true):14} {computus(year, false):6}".fmt |
0 commit comments