Вычисление дня недели — это JS с помощью Sakamoto, Wang, Schwerdtfeger

#javascript #dayofweek

#javascript #день недели

Вопрос:

Я пытаюсь реализовать функцию «получить день недели» (Su = 0, Mo, …, Sa = 6) в обычном javascript и наткнулся на алгоритм Томохико Сакамото, Вана и Швердтфегера. Насколько я понимаю, все три применяют одну и ту же концепцию, только с разными шагами, поэтому я просто сосредоточусь на алгоритме Сакамото здесь для простоты. Я написал простую тестовую функцию для проверки правильности их результатов, но все они, похоже, идут не так в 2004-March-1st, который рассчитывается как воскресенье (0), а на самом деле является понедельником (1).

Я ошибаюсь или есть какие-то особые границы для алгоритма, о которых я не знаю?

 const DaysInMonth = [
  31, // Jan
  28, // Feb has 29 in leap years!
  31, // Mar
  30, // Apr
  31, // May
  30, // Jun
  31, // Jul
  31, // Aug
  30, // Sep
  31, // Okt
  30, // Nov
  31 // Dec
]

function getWeekDaySakamoto (y, m ,d) {
  const LookupTable = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
  let year = y
  if (m < 3) {
   year -= 1
  }
  return Math.floor((year   year / 4 - year / 100   year / 400   LookupTable[m - 1]   d) % 7)
}

let isLeap = false
let wd = 0
let prevWd = -1
// we need to findout where the algo goes wrong
for (let y = 2000; y < 2030; y  ) {
  isLeap = y % 4 === 0
  if (isLeap amp;amp; y % 100 === 0 amp;amp; y % 400 !== 0) {
    isLeap = false
  }
  for (let m = 1; m <= 12; m  ) {
    for (let d = 1; isLeap amp;amp; m === 2 ? (d <= 29) : (d <= DaysInMonth[m - 1]); d  ) {
      wd = getWeekDaySakamoto(y, m ,d)
      if (prevWd === -1) {
        // initialize the value first
        prevWd = wd
      } else {
        if ((wd === 0 amp;amp; prevWd === 6) ||
          (wd === 1 amp;amp; prevWd === 0) ||
          (wd === 2 amp;amp; prevWd === 1) ||
          (wd === 3 amp;amp; prevWd === 2) ||
          (wd === 4 amp;amp; prevWd === 3) ||
          (wd === 5 amp;amp; prevWd === 4) ||
          (wd === 6 amp;amp; prevWd === 5)) {
          console.log(`checked ${y}-${m}-${d} = ${wd}`)
          prevWd = wd
        } else {
          throw new Error(`expected ${y}-${m}-${d} to be a follow up on ${prevWd} but got ${wd}`)
        }
      }
    }
  }
} 

Окончательное сообщение об ошибке сценария проверки Error: expected 2004-3-1 to be a follow up on 0 but got 0 выглядит так, как 2004-2-29 было a 0 (что правильно), 2004-3-1 должно быть a, 1 но 0 вместо этого вычисляется как a .