#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 .