Last active
December 7, 2019 14:08
-
-
Save bathos/84286d0d6052d10dd98a444d41e9db43 to your computer and use it in GitHub Desktop.
/util/date/weekdata.mjs
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
import range from '/util/iterator/range.mjs'; | |
// Week start data pulled from similarly golfed answer on SO: | |
// https://stackoverflow.com/a/57102881/1631952 | |
// | |
// I’m not thrilled with this; we probably ought to be generating it since the | |
// data is pretty obscure. OTOH I’d be far less thrilled with loading hefty | |
// chunks of ICU data and this is pretty solid and compact! | |
// | |
// Note that the RegExp given for lang tags in that answer is a bit off. The one | |
// below is more accurate but deliberately doesn’t bother matching any segments | |
// after region and doesn’t include grandfathered tags etc, since browsers | |
// should not be returning those values. It also does not bother matching region | |
// tag segments which use the three-digit format since we don’t have data for | |
// those below (and again I doubt browsers ever surface language tags that way). | |
// | |
// The exports here are live. Queue a render on languagechange in elements that | |
// consume this data if you want it to respond to system language changes. In | |
// practice, such events are very rare and on Windows they don’t reliably | |
// occur, so it’s your call whether it’s worthwhile in a given case. | |
const LANG_TAG_REGION = | |
/^(?:[a-z]{2,3}(?:-[a-z]{3}){0,3}|[a-z]{4,8})(?:-[a-z]{4})?-([a-z]{2})/i; | |
// ^ lang (1) ^ extlangs ^ lang (2) ^ script ^ region | |
const [ SATURDAYS, SUNDAYS ] = [ | |
'AEAFBHDJDZEGIQIRJOKWLYOMQASDSY', | |
'AGARASAUBDBRBSBTBWBZCACNCODMDOETGTGUHKHNIDILINJMJPKEKHKRLAMHMMMOMTMXMZNINP' + | |
'PAPEPHPKPRPTPYSASGSVTHTTTWUMUSVEVIWSYEZAZW' | |
].map(src => new Set(src.split(/(?=(..)+$)/))); | |
//////////////////////////////////////////////////////////////////////////////// | |
export let indices, longNames, shortNames, start; | |
update(); | |
addEventListener('languagechange', update); | |
//////////////////////////////////////////////////////////////////////////////// | |
function getRegion() { | |
for (const tag of navigator.languages) { | |
const match = LANG_TAG_REGION.exec(tag); | |
if (match) { | |
return match[1].toUpperCase(); | |
} | |
} | |
} | |
function getWeekNames(format) { | |
return indices.map(i => { | |
const date = new Date(0, 0, i); | |
return date.toLocaleDateString(navigator.languages, { | |
calendar: 'gregory', | |
weekday: format | |
}); | |
}); | |
} | |
function update() { | |
const region = getRegion(); | |
start = SATURDAYS.has(region) ? 6 : SUNDAYS.has(region) ? 0 : 1; | |
indices = Array.from(range(0, 7), i => (start + i) % 7); | |
shortNames = getWeekNames('short'); | |
longNames = getWeekNames('long'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment