Last active
February 4, 2023 00:04
-
-
Save hagemt/50bb22c30040932bc23c2fe16fb44c4b to your computer and use it in GitHub Desktop.
NodeJS exercise in commenting code/test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global console, process */ | |
// | |
// mild JS surprises in the Date API | |
// - getDay() returns 0=Sunday day of week, vs. getDate()'s day of month | |
// - getMonth() returns 0 for January, which isn't how getDate() works | |
// - getYear() vs. getFullYear() for year X vs. 1900 + X | |
// | |
// JS puts 0=Sunday first, but Zeller considers 0=Saturday (modulate once left) | |
const days = Object.freeze(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']) | |
const day7 = (id, add = -1) => days[((id + add) % 7 + 7) % 7] // map Mon-Sun | |
// return the equivalent of (JS's full year, month of year, day of month) | |
const tYMD = (d = Date.now(), DateClass = Date) => { | |
// http://howardhinnant.github.io/date_algorithms.html | |
const dt = new DateClass(d) // exercise: implement yourself | |
return [dt.getFullYear(), dt.getMonth(), dt.getDate()] | |
} | |
// calculate day-of-week by hand, equivalent of days[new Date(d).getDay()] | |
const dow = (d = Date.now(), julian = false) => { | |
const [y, month, dom] = tYMD(d) // 0=January; thanks, JavaScript | |
const delay = month < 2 // Jan or Feb count as month 13 and 14 | |
const year = delay ? y - 1 : y // of "last year" vs. this one | |
// https://en.wikipedia.org/wiki/Zeller%27s_congruence | |
const q = dom // day of month | |
const m = delay ? 13 + month : 1 + month // [0-11] => [13,14,3,...,11] | |
const i = q + Math.floor(13 * (m + 1) / 5) + year + Math.floor(year / 4) | |
const c = julian ? 5 : Math.floor(year / 400) - Math.floor(year / 100) | |
return day7(i + c) // julian correction=5 days vs. standard Gregorian | |
} | |
const test = () => { | |
const max = parseInt(process.env.STOP || 10000000) // day count to simulate | |
const now = new Date(process.env.ZERO || Date.now()) // anything epoch-like | |
const plusDays = (i, zero = now) => new Date(+zero + i*1000*3600*24) | |
const okayDate = (i, fail = Number.isNaN) => !fail(plusDays(i).getTime()) | |
for (let i = 0; i < max && okayDate(i); i += 1) { | |
const a = dow(+plusDays(i)) // actual DOW vs. expected (i days added) | |
const e = day7(plusDays(i).getDay(), 0) // JS order starts with Sunday | |
if (a !== e) console.error('wrong:', plusDays(i).toString(), 'is not', a) | |
} | |
} | |
// will print out any date cases in range where DOW is unexpected | |
//test() // alternative / simpler test: console.log(dow(Date.now())) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment