Skip to content

Instantly share code, notes, and snippets.

@hagemt
Last active February 4, 2023 00:04
Show Gist options
  • Save hagemt/50bb22c30040932bc23c2fe16fb44c4b to your computer and use it in GitHub Desktop.
Save hagemt/50bb22c30040932bc23c2fe16fb44c4b to your computer and use it in GitHub Desktop.
NodeJS exercise in commenting code/test
/* 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