Implementing the Easter algorithm

A simple JavaScript program that illustrates how scientific code becomes a mess

I implemented Gauss’s Easter algorithm in JavaScript. You can play with the program at https://easter.antonischristofides.com/ and find the date in any year you like (but years prior to 1582 might not work correctly, and the result wouldn’t make sense anyway).

The heart of the program is the `getEasterDate()` function, which I include below. I wrote it quickly and it suffers from the problems most scientific code suffers. Essentially it’s hard to understand. But the problem is that the algorithm itself is hard to understand. Can we make the algorithm and the program easier to understand? I will start exploring this question in my next post.

Here is the boring code I promised (the full thing is at https://github.com/aptiko/easter):

function getEasterDate(year, type) {
  let month;
  let dayOfMonth;
  let M;
  let N;

  const a = year % 19;
  const b = year % 4;
  const c = year % 7;
  if (['julian', 'orthodox'].includes(type)) {
    M = 15;
    N = 6;
  } else {
    const k = Math.floor(year / 100);
    const p = Math.floor((13 + 8 * k) / 25);
    const q = Math.floor(k / 4);
    M = (15 - p + k - q) % 30;
    N = (4 + k - q) % 7;
  }
  const d = (19 * a + M) % 30;
  const e = (2 * b + 4 * c + 6 * d + N) % 7;
  if (d === 29 && e === 6) {
    month = 4;
    dayOfMonth = 19;
  } else if (d === 28 && e === 6 && (11 * M + 11) % 30 < 19) {
    month = 4;
    dayOfMonth = 18;
  } else {
    month = 3;
    dayOfMonth = 22 + d + e;
  }
  if (dayOfMonth > 31) {
    month = 4;
    dayOfMonth -= 31;
  }
  if (type === 'orthodox') {
    dayOfMonth += julianDifference(year);
  }
  if (dayOfMonth > monthDays(month)) {
    dayOfMonth -= monthDays(month);
    month += 1;
  }
  return [month, dayOfMonth];
}