From 2cf33ba2d83adadce628c4eee3859e0c9f4121dc Mon Sep 17 00:00:00 2001 From: Nick Stokoe Date: Sat, 31 Dec 2022 01:41:29 +0000 Subject: [PATCH] www/{countdown.js,index.html} - nominally working? --- www/countdown.js | 298 +++++++++++++++++++++++++++++++++++++---------- www/index.html | 4 +- 2 files changed, 239 insertions(+), 63 deletions(-) diff --git a/www/countdown.js b/www/countdown.js index 247ee5a..0ecf120 100644 --- a/www/countdown.js +++ b/www/countdown.js @@ -1,64 +1,224 @@ -var events = [ - { time: new Date("Tue 31 Dec 2022 10:00:00 GMT"), country: "Christmas Island/Kiribati and Samoa", city: "Kiritimati, Apia" }, - { time: new Date("Tue 31 Dec 2022 10:15:00 GMT"), country: "Chatham Islands/New Zealand", city: "Chatham Islands" }, - { time: new Date("Tue 31 Dec 2022 11:00:00 GMT"), country: "New Zealand with exceptions and 5 more", city: "Auckland, Suva, Wellington, Nukualofa" }, - { time: new Date("Tue 31 Dec 2022 12:00:00 GMT"), country: "small region of Russia, Marshall Islands and 5 more", city: "Anadyr, Funafuti, Yaren, Tarawa" }, - { time: new Date("Tue 31 Dec 2022 12:30:00 GMT"), country: "Norfolk Island", city: "Kingston" }, - { time: new Date("Tue 31 Dec 2022 13:00:00 GMT"), country: "much of Australia and 5 more", city: "Melbourne, Sydney, Canberra, Honiara" }, - { time: new Date("Tue 31 Dec 2022 13:30:00 GMT"), country: "small region of Australia", city: "Adelaide, Broken Hill" }, - { time: new Date("Tue 31 Dec 2022 14:00:00 GMT"), country: "Queensland/Australia and 5 more", city: "Brisbane, Port Moresby, Guam (Hagåtña), Cairns" }, - { time: new Date("Tue 31 Dec 2022 14:30:00 GMT"), country: "Northern Territory/Australia", city: "Darwin, Alice Springs, Uluru" }, - { time: new Date("Tue 31 Dec 2022 15:00:00 GMT"), country: "Japan and 6 more", city: "Tokyo, Seoul, Pyongyang, Dili" }, - { time: new Date("Tue 31 Dec 2022 15:15:00 GMT"), country: "Western Australia/Australia", city: "Eucla" }, - { time: new Date("Tue 31 Dec 2022 16:00:00 GMT"), country: "China and 12 more", city: "Beijing, Hong Kong, Manila, Singapore" }, - { time: new Date("Tue 31 Dec 2022 17:00:00 GMT"), country: "much of Indonesia, Thailand and 7 more", city: "Jakarta, Bangkok, Hanoi, Phnom Penh" }, - { time: new Date("Tue 31 Dec 2022 17:30:00 GMT"), country: "Myanmar and Cocos Islands", city: "Yangon, Naypyidaw, Mandalay, Bantam" }, - { time: new Date("Tue 31 Dec 2022 18:00:00 GMT"), country: "Bangladesh, some regions of Russia and 4 more", city: "Dhaka, Almaty, Bishkek, Thimphu" }, - { time: new Date("Tue 31 Dec 2022 18:15:00 GMT"), country: "Nepal", city: "Kathmandu, Biratnagar, Pokhara" }, - { time: new Date("Tue 31 Dec 2022 18:30:00 GMT"), country: "India and Sri Lanka", city: "New Delhi, Mumbai, Kolkata, Bangalore" }, - { time: new Date("Tue 31 Dec 2022 19:00:00 GMT"), country: "Pakistan and 8 more", city: "Tashkent, Islamabad, Lahore, Karachi" }, - { time: new Date("Tue 31 Dec 2022 19:30:00 GMT"), country: "Afghanistan", city: "Kabul, Kandahar, Mazari Sharif, Herat" }, - { time: new Date("Tue 31 Dec 2022 20:00:00 GMT"), country: "much of Russia and 8 more", city: "Moscow, Dubai, Abu Dhabi, Muscat" }, - { time: new Date("Tue 31 Dec 2022 20:30:00 GMT"), country: "Iran", city: "Tehran, Rasht, Esfahãn, Bandar-Abbas" }, - { time: new Date("Tue 31 Dec 2022 21:00:00 GMT"), country: "Iraq and 20 more", city: "Baghdad, Khartoum, Nairobi, Addis Ababa" }, - { time: new Date("Tue 31 Dec 2022 22:00:00 GMT"), country: "Greece and 30 more", city: "Cairo, Ankara, Athens, Bucharest" }, - { time: new Date("Tue 31 Dec 2022 23:00:00 GMT"), country: "Germany and 43 more", city: "Brussels, Madrid, Paris, Rome" }, - { time: new Date("Wed 1 Jan 2023 00:00:00 GMT"), country: "United Kingdom and 24 more", city: "London, Casablanca, Dublin, Lisbon" }, +// This is deliberately browser-compatible JS, so we avoid fat arrows etc. - { time: new Date("Wed 1 Jan 2023 1:00:00 GMT"), country: "Cape Verde, some regions of Greenland and 1 more", city: "Praia, Ponta Delgada (Azores), Ittoqqortoormiit, Mindelo" }, - { time: new Date("Wed 1 Jan 2023 2:00:00 GMT"), country: "regions of Brazil, Uruguay and 1 more", city: "Rio de Janeiro, São Paulo, Brasilia, Wed 1 Jan 2023tevideo" }, - { time: new Date("Wed 1 Jan 2023 3:00:00 GMT"), country: "regions of Brazil, Argentina and 7 more", city: "Buenos Aires, Santiago, Asuncion, Paramaribo" }, - { time: new Date("Wed 1 Jan 2023 3:30:00 GMT"), country: "Newfoundland and Labrador/Canada", city: "St. John's, Conception Bay South, Corner Brook, Gander" }, - { time: new Date("Wed 1 Jan 2023 4:00:00 GMT"), country: "some regions of Canada and 26 more", city: "La Paz, San Juan, Santo Domingo, Halifax" }, - { time: new Date("Wed 1 Jan 2023 4:30:00 GMT"), country: "Venezuela", city: "Caracas, Barquisimeto, Maracaibo, Maracay" }, - { time: new Date("Wed 1 Jan 2023 5:00:00 GMT"), country: "regions of U.S.A., regions of Canada and 12 more", city: "New York, Washington DC, Detroit, Havana" }, - { time: new Date("Wed 1 Jan 2023 6:00:00 GMT"), country: "regions of U.S.A., some regions of Canada and 8 more", city: "Mexico City, Chicago, Guatemala, Dallas" }, - { time: new Date("Wed 1 Jan 2023 7:00:00 GMT"), country: "some regions of U.S.A., some regions of Canada and 1 more", city: "Calgary, Denver, Edmonton, Phoenix" }, - { time: new Date("Wed 1 Jan 2023 8:00:00 GMT"), country: "regions of U.S.A., some regions of Canada and 2 more", city: "Los Angeles, San Francisco, Las Vegas, Seattle" }, - { time: new Date("Wed 1 Jan 2023 9:00:00 GMT"), country: "Alaska/U.S.A. and French Polynesia", city: "Anchorage, Fairbanks, Unalaska, Juneau" }, - { time: new Date("Wed 1 Jan 2023 9:30:00 GMT"), country: "Marquesas Islands/France", city: "Taiohae" }, - { time: new Date("Wed 1 Jan 2023 10:00:00 GMT"), country: "small region of U.S.A. and 2 more", city: "Honolulu, Rarotonga, Adak, Papeete" }, - { time: new Date("Wed 1 Jan 2023 11:00:00 GMT"), country: "American Samoa, Midway Atoll/U.S.A. and 1 more", city: "Alofi, Midway, Pago Pago" }, - { time: new Date("Wed 1 Jan 2023 12:00:00 GMT"), country: "small region of U.S.A.", city: "Baker Island, Howland Island" }, -]; -/* - var events = [ - { time: new Date("Tue 31 Dec 2022 1:00:00 GMT"), country: "Cape Verde, some regions of Greenland and 1 more", city: "Praia, Ponta Delgada (Azores), Ittoqqortoormiit, Mindelo" }, - { time: new Date("Tue 31 Dec 2022 2:00:00 GMT"), country: "regions of Brazil, Uruguay and 1 more", city: "Rio de Janeiro, São Paulo, Brasilia, Tue 31 Dec 2022tevideo" }, - { time: new Date("Tue 31 Dec 2022 2:30:00 GMT"), country: "regions of Brazil, Argentina and 7 more", city: "Buenos Aires, Santiago, Asuncion, Paramaribo" }, - { time: new Date("Tue 31 Dec 2022 2:45:00 GMT"), country: "Newfoundland and Labrador/Canada", city: "St. John's, Conception Bay South, Corner Brook, Gander" }, - ]; -*/ -var now = new Date().getTime(); +var locale = "EN-GB"; +var now = new Date(); +var nextNewYearUTC = new Date(Date.UTC(now.getFullYear()+1, 0, 1)); var secsRemaining = 0; -var nextEvent; +var nextZone; var counter = document.getElementById("counter"); var loc = document.getElementById("location"); var time = document.getElementById("localtime"); +var untilDate = document.getElementById("until-date"); var countDownSound = new Audio('get-ready.ogg'); +// Convert the next new year time to 'date, hours:mins:secs' in the target timezone +function zoneTime(zone, refTime) { + return refTime.toLocaleString('EN-US', { + hour: '2-digit', + hour12: false, + minute: '2-digit', + second: '2-digit', + year: 'numeric', + month: 'numeric', + day: 'numeric', + timeZone: zone, + }); +} +function zoneOffsetMillis(timestr, baseDate) { + var v = timestr.split(/[/ :,]+/) + .map(function(str) { return Number(str); }); + var date = new Date(v[2],v[0]-1,v[1],v[3],v[4],v[5]); + return date.valueOf() - baseDate.valueOf(); +} + +// Compile a list of timezones from Intl.supportedValuesOf +var zones = Intl.supportedValuesOf('timeZone') + .map(function(zone) { return { + zone: zone, + offset: zoneOffsetMillis(zoneTime(zone, nextNewYearUTC), nextNewYearUTC) + }; }) + .sort(function(a,b) { return b.offset - a.offset; }); + +// Now concoct an index of timezone hour offsets to timezone info. +// Each zone has: +// { abbrevs, offset, hOffset, nydDate } +var zoneIndex = zones + .reduce((a, v) => { + var hOffset = v.offset/3600000; + var zoneInfo = a[hOffset]; + if (zoneInfo) + zoneInfo.abbrevs.push(v.zone); + else { + a[hOffset] = { + abbrevs: [v.zone], + offset: v.offset, + hOffset: hOffset, + nydDate: new Date(nextNewYearUTC.valueOf() + v.offset), + }; + } + return a; + }, {}); +console.debug(nextNewYearUTC, zoneIndex); + +// This info is just used to say what cities / countries are in the timezone +var zoneInfo = { + "-12": { + country: "small region of U.S.A.", + city: "Baker Island, Howland Island" + }, + "-11": { + country: "American Samoa, Midway Atoll/U.S.A. and 1 more", + city: "Alofi, Midway, Pago Pago" + }, + "-10": { + country: "Cook Islands, small region of U.S.A. and 2 more", + city: "Honolulu, Rarotonga, Adak, Papeete" + }, + "-9.5": { + country: "French Polynesia, Marquesas Islands", + city: "Taiohae" + }, + "-9": { + country: "Alaska/U.S.A. and French Polynesia", + city: "Anchorage, Fairbanks, Unalaska, Juneau" + }, + "-8": { + country: "Pitcairn Islands, regions of U.S.A. Mexico, and Canada", + city: "Los Angeles, San Francisco, Las Vegas, Seattle" + }, + "-7": { + country: "some regions of U.S.A., Mexico, some regions of Canada", + city: "Calgary, Denver, Edmonton, Phoenix" + }, + "-6": { + country: "Belize, regions of U.S.A., Mexico, some regions of Canada and 8 more", + city: "Mexico City, Chicago, Guatemala, Dallas" + }, + "-5": { + country: "regions of U.S.A., regions of Canada and 12 more", + city: "New York, Washington DC, Detroit, Havana" + }, + "-4": { + country: "Venezuela", + city: "Caracas, Barquisimeto, Maracaibo, Maracay" + }, + "-3.5": { + country: "Newfoundland and Labrador/Canada", + city: "St. John's, Conception Bay South, Corner Brook, Gander" + }, + "-3": { + country: "regions of Brazil, Argentina and 7 more", + city: "Buenos Aires, Santiago, Asuncion, Paramaribo" + }, + "-2": { + country: "South Georgia and the South Sandwich Islands", + city: "Grytviken", + }, + "-1": { + country: "Cape Verde, some regions of Greenland and 1 more", + city: "Praia, Ponta Delgada (Azores), Ittoqqortoormiit, Mindelo" + }, + "0": { + country: "United Kingdom and 24 more", + city: "London, Casablanca, Dublin, Lisbon" + }, + "1": { + country: "Germany and 43 more", + city: "Brussels, Madrid, Paris, Rome" + }, + "2": { + country: "Greece and 30 more", + city: "Cairo, Ankara, Athens, Bucharest" + }, + "3": { + country: "Iraq and 20 more", + city: "Baghdad, Khartoum, Nairobi, Addis Ababa" + }, + "3.5": { + country: "Iran", + city: "Tehran, Rasht, Esfahãn, Bandar-Abbas" + }, + "4": { + country: "UAE, parts of Russia, Georgia, Armenia, Mauritius", + city: "Tblisi, Dubai, Abu Dhabi", + }, + "4.5": { + country: "Afghanistan", + city: "Kabul, Kandahar, Mazari Sharif, Herat" + }, + "5": { + country: "Pakistan and 8 more", + city: "Tashkent, Islamabad, Lahore, Karachi" + }, + "5.5": { + country: "India and Sri Lanka", + city: "New Delhi, Mumbai, Kolkata, Bangalore" + }, + "5.75": { + country: "Nepal", + city: "Kathmandu, Biratnagar, Pokhara" + }, + "6": { + country: "Bangladesh, some regions of Russia and 4 more", + city: "Dhaka, Almaty, Bishkek, Thimphu" + }, + "6.5": { + country: "Myanmar and Cocos Islands", + city: "Yangon, Naypyidaw, Mandalay, Bantam" + }, + "7": { + country: "much of Indonesia, Thailand and 7 more", + city: "Jakarta, Bangkok, Hanoi, Phnom Penh" + }, + "8": { + country: "China and 12 more", + city: "Beijing, Hong Kong, Manila, Singapore" + }, + "8.75": { + country: "Western Australia/Australia", + city: "Eucla" + }, + "9": { + country: "Japan and 6 more", + city: "Tokyo, Seoul, Pyongyang, Dili" + }, + "9.5": { + country: "Northern Territory/Australia", + city: "Darwin, Alice Springs, Uluru" + }, + "10": { + country: "Queensland/Australia and 5 more", + city: "Brisbane, Port Moresby, Guam (Hagåtña), Cairns" + }, + "10.5": { + country: "small region of Australia", + city: "Adelaide, Broken Hill" + }, + "11": { + country: "Vanuatu, Solomon Islands, much of Australia and 5 more", + city: "Melbourne, Sydney, Canberra, Honiara" + }, + "12": { + country: "Kiribati, Marshall Islands, Norfolk Island, Tuvalu, Fiji", + city: "Kingston", + }, + "13": { + country: "New Zealand with exceptions and 5 more", + city: "Auckland, Suva, Wellington, Nukualofa" + }, + "13.75": { + country: "Chatham Islands/New Zealand", + city: "Chatham Islands" + }, +}; +console.debug(zoneInfo); + +var zoneOrder = Object.keys(zoneIndex) + .map(Number) + .sort(function(a,b) { return a-b; }); +console.debug(zoneOrder); function pad(num) { return (num<10? "0"+num : ""+num); @@ -82,24 +242,24 @@ function timeRemaining(millisecsRemaining) { millisecsRemaining -= mins * 60000 var secs = Math.round(millisecsRemaining / 1000) - return hours+":"+pad(mins)+":"+pad(secs) + return hours+"h "+pad(mins)+"m "+pad(secs)+"s" } var playing = false; function handleTick(now) { - console.log(now, now.getMilliseconds()); + console.debug(now, now.getMilliseconds()); - while (!nextEvent || nextEvent.time <= now) { - if (events.length == 0) return; + while (!nextZone || zoneIndex[nextZone].nydDate <= now) { + if (zoneOrder.length == 0) return; - nextEvent = events.shift(); + nextZone = zoneOrder.shift(); + console.debug("next up: zone", nextZone); } - - var millisecsRemaining = nextEvent.time.getTime() - now.getTime(); + var millisecsRemaining = zoneIndex[nextZone].nydDate.getTime() - now.getTime(); var excl = millisecsRemaining < 1000*5? "!" : ""; - console.log("seconds",now.getSeconds()); + console.debug("seconds",now.getSeconds()); if (millisecsRemaining < 2*60*1000) { if (!playing) { countDownSound.play(); @@ -110,9 +270,23 @@ function handleTick(now) { // resets the announcement playing = false; + var info = zoneInfo[nextZone]; + var zone = zoneIndex[nextZone]; + + untilDate.innerHTML = nextNewYearUTC.toLocaleDateString(locale, { + weekday: "long", + year: "numeric", + month: "long", + day: "numeric", + }); counter.innerHTML = timeRemaining(millisecsRemaining); - loc.innerHTML = nextEvent.city; - time.innerHTML = nextEvent.time.toLocaleFormat("%I:%M %p") + loc.innerHTML = info? info.city || info.country : zone.abbrev[0]; + + time.innerHTML = zone.nydDate.toLocaleDateString(locale, { + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + }); counter.className = counterClass(millisecsRemaining); } diff --git a/www/index.html b/www/index.html index 7dba3f2..684e776 100644 --- a/www/index.html +++ b/www/index.html @@ -8,7 +8,7 @@ text-align: center; } div#counter { - font-size: 180pt; + font-size: 100pt; text-align: left; } div#location { @@ -30,5 +30,7 @@
+ +