英文:
Javascript count down to UTC 4am every day & every Sunday
问题
我正在为一个每天和每周都有重置的MMORPG(游戏)构建资源。一个重置是每周日UTC时间上午4点,另一个是每天UTC时间上午4点。我希望在页面顶部显示倒计时计时器来显示这些重置。
下面的JavaScript代码是每天倒计时到午夜。我该如何修改这段代码,以便我可以构建两个倒计时。一个是倒计时到UTC时间上午4点(每天),另一个是倒计时到每周日UTC时间上午4点?
var div = document.getElementById("bb");
setInterval(function() {
var toDate = new Date();
var tomorrow = new Date();
tomorrow.setHours(24, 0, 0, 0);
var diffMS = tomorrow.getTime() / 1000 - toDate.getTime() / 1000;
var diffHr = Math.floor(diffMS / 3600);
diffMS = diffMS - diffHr * 3600;
var diffMi = Math.floor(diffMS / 60);
diffMS = diffMS - diffMi * 60;
var diffS = Math.floor(diffMS);
var result = ((diffHr < 10) ? "0" + diffHr : diffHr);
result += ":" + ((diffMi < 10) ? "0" + diffMi : diffMi);
result += ":" + ((diffS < 10) ? "0" + diffS : diffS);
div.innerHTML = result;
},1000);
<div id="bb">
</div>
英文:
I am building a resource for an MMORPG (game) that has daily and weekly resets. One reset is every Sunday @ 4am UTC and another is every day @ 4am UTC. I am looking to display countdown timers at the top of a page for these resets.
This Javascript code below counts down to midnight each day. How can I modify this code so I can build 2 countdowns. 1 that counts down to 4am UTC (daily) and another that counts down to 4am UTC every Sunday?
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
var div = document.getElementById("bb");
setInterval(function() {
var toDate = new Date();
var tomorrow = new Date();
tomorrow.setHours(24, 0, 0, 0);
var diffMS = tomorrow.getTime() / 1000 - toDate.getTime() / 1000;
var diffHr = Math.floor(diffMS / 3600);
diffMS = diffMS - diffHr * 3600;
var diffMi = Math.floor(diffMS / 60);
diffMS = diffMS - diffMi * 60;
var diffS = Math.floor(diffMS);
var result = ((diffHr < 10) ? "0" + diffHr : diffHr);
result += ":" + ((diffMi < 10) ? "0" + diffMi : diffMi);
result += ":" + ((diffS < 10) ? "0" + diffS : diffS);
div.innerHTML = result;
},1000);
<!-- language: lang-html -->
<div id="bb">
</div>
<!-- end snippet -->
答案1
得分: 1
我已经使用你之前提供的代码进行了以下修改:
var div = document.getElementById("bb");
var div2 = document.getElementById("bc");
setInterval(function() {
var toDate = new Date();
var timezoneOffset = toDate.getTimezoneOffset() / 60; // 与 GMT 的小时差
var tomorrow = new Date();
tomorrow.setHours(4, 0, 0); // 将时间设置为明天的凌晨4点
var diffMS = tomorrow.getTime() / 1000 - toDate.getTime() / 1000;
var diffHr = Math.floor(diffMS / 3600);
diffMS = diffMS - diffHr * 3600;
var diffMi = Math.floor(diffMS / 60);
diffMS = diffMS - diffMi * 60;
var diffS = Math.floor(diffMS);
diffHr -= timezoneOffset;
var result = ((diffHr < 10) ? "0" + diffHr : diffHr);
result += ":" + ((diffMi < 10) ? "0" + diffMi : diffMi);
result += ":" + ((diffS < 10) ? "0" + diffS : diffS);
div.innerHTML = result;
var nextSunday = getNextSunday(new Date());
nextSunday.setHours(4, 0, 0);
diffMS = nextSunday.getTime() / 1000 - toDate.getTime() / 1000;
diffHr = Math.floor(diffMS / 3600);
diffMS = diffMS - diffHr * 3600;
diffMi = Math.floor(diffMS / 60);
diffMS = diffMS - diffMi * 60;
diffS = Math.floor(diffMS);
diffHr -= timezoneOffset;
result = ((diffHr < 10) ? "0" + diffHr : diffHr);
result += ":" + ((diffMi < 10) ? "0" + diffMi : diffMi);
result += ":" + ((diffS < 10) ? "0" + diffS : diffS);
div2.innerHTML = result;
}, 1000);
function getNextSunday(d) {
var t = new Date(d);
t.setDate(d.getDate() + (7 - d.getDay()) % 7);
return t;
}
首先,我对 tomorrow
进行了小的修改,将时间增加了4小时,这样它就设置为凌晨4点,而不是午夜。
然后,我只是添加了另一个 div
,用于显示从现在到周日凌晨4点的时间,并在底部添加了一个获取下一个周日日期的函数。
我添加了一个用于 UTC 转换的偏移量,该偏移量在最后应用。除此之外,代码与你之前编写的几乎完全相同!
英文:
I've written this code below using what you had already:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
var div = document.getElementById("bb");
var div2 = document.getElementById("bc");
setInterval(function() {
var toDate = new Date();
var timezoneOffset = toDate.getTimezoneOffset() / 60; // difference in hours from GMT
var tomorrow = new Date();
tomorrow.setHours(28, 0, 0);
var diffMS = tomorrow.getTime() / 1000 - toDate.getTime() / 1000;
var diffHr = Math.floor(diffMS / 3600);
diffMS = diffMS - diffHr * 3600;
var diffMi = Math.floor(diffMS / 60);
diffMS = diffMS - diffMi * 60;
var diffS = Math.floor(diffMS);
diffHr -= timezoneOffset;
var result = ((diffHr < 10) ? "0" + diffHr : diffHr);
result += ":" + ((diffMi < 10) ? "0" + diffMi : diffMi);
result += ":" + ((diffS < 10) ? "0" + diffS : diffS);
div.innerHTML = result;
var nextSunday = getNextSunday(new Date());
nextSunday.setHours(4, 0, 0);
diffMS = nextSunday.getTime() / 1000 - toDate.getTime() / 1000;
diffHr = Math.floor(diffMS / 3600);
diffMS = diffMS - diffHr * 3600;
diffMi = Math.floor(diffMS / 60);
diffMS = diffMS - diffMi * 60;
diffS = Math.floor(diffMS);
diffHr -= timezoneOffset;
result = ((diffHr < 10) ? "0" + diffHr : diffHr);
result += ":" + ((diffMi < 10) ? "0" + diffMi : diffMi);
result += ":" + ((diffS < 10) ? "0" + diffS : diffS);
div2.innerHTML = result;
}, 1000);
function getNextSunday(d) {
var t = new Date(d);
t.setDate(d.getDate() + (7 - d.getDay()) % 7);
return t;
}
<!-- language: lang-html -->
<div id="bb">
</div>
<div id="bc">
</div>
<!-- end snippet -->
Firstly, I made a small change to add 4 hours to tomorrow
so that it's set for 4 am, instead of midnight.
Afterwards, I just added another div
where I can put the time between now and Sunday at 4 am and a function to get the date for the next Sunday at the bottom.
I added an offset for the UTC conversion which is applied at the end. After that, the code is almost identical to what you had already written!
答案2
得分: 0
请尝试以下代码:
var dailyResetDiv = document.getElementById("dailyReset");
var weeklyResetDiv = document.getElementById("weeklyReset");
function updateCountdown(targetDate, outputElement) {
var now = new Date();
var diffMS = targetDate.getTime() - now.getTime();
var diffHr = Math.floor(diffMS / 3600000);
diffMS = diffMS - diffHr * 3600000;
var diffMi = Math.floor(diffMS / 60000);
diffMS = diffMS - diffMi * 60000;
var diffS = Math.floor(diffMS / 1000);
var result =
(diffHr < 10 ? "0" + diffHr : diffHr) +
":" +
(diffMi < 10 ? "0" + diffMi : diffMi) +
":" +
(diffS < 10 ? "0" + diffS : diffS);
outputElement.innerHTML = result;
}
setInterval(function () {
// 每天在UTC时间的凌晨4点重置
var dailyReset = new Date();
dailyReset.setUTCHours(4, 0, 0, 0);
updateCountdown(dailyReset, dailyResetDiv);
// 每周在UTC时间的星期日凌晨4点重置
var weeklyReset = new Date();
weeklyReset.setUTCHours(4, 0, 0, 0);
var dayOfWeek = weeklyReset.getUTCDay();
if (dayOfWeek !== 0) {
// 如果不是星期日,将日期调整到下一个星期日
weeklyReset.setUTCDate(weeklyReset.getUTCDate() + (7 - dayOfWeek));
}
updateCountdown(weeklyReset, weeklyResetDiv);
}, 1000);
<div id="dailyReset"></div>
<div id="weeklyReset"></div>
英文:
Try this code:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
var dailyResetDiv = document.getElementById("dailyReset");
var weeklyResetDiv = document.getElementById("weeklyReset");
function updateCountdown(targetDate, outputElement) {
var now = new Date();
var diffMS = targetDate.getTime() - now.getTime();
var diffHr = Math.floor(diffMS / 3600000);
diffMS = diffMS - diffHr * 3600000;
var diffMi = Math.floor(diffMS / 60000);
diffMS = diffMS - diffMi * 60000;
var diffS = Math.floor(diffMS / 1000);
var result =
(diffHr < 10 ? "0" + diffHr : diffHr) +
":" +
(diffMi < 10 ? "0" + diffMi : diffMi) +
":" +
(diffS < 10 ? "0" + diffS : diffS);
outputElement.innerHTML = result;
}
setInterval(function () {
// Daily reset at 4am UTC
var dailyReset = new Date();
dailyReset.setUTCHours(4, 0, 0, 0);
updateCountdown(dailyReset, dailyResetDiv);
// Weekly reset on Sunday at 4am UTC
var weeklyReset = new Date();
weeklyReset.setUTCHours(4, 0, 0, 0);
var dayOfWeek = weeklyReset.getUTCDay();
if (dayOfWeek !== 0) {
// If not Sunday, adjust the date to the next Sunday
weeklyReset.setUTCDate(weeklyReset.getUTCDate() + (7 - dayOfWeek));
}
updateCountdown(weeklyReset, weeklyResetDiv);
}, 1000);
<!-- language: lang-html -->
<div id="dailyReset"></div>
<div id="weeklyReset"></div>
<!-- end snippet -->
答案3
得分: 0
你可以尝试使用面向对象编程(OOP)的方法,创建一个计时器类(timer class)。你只需要计算目标日期一次,计时器将在一定时间间隔内调用渲染函数。
以下是代码示例:
const localTimeEl = document.querySelector('#local-time');
const utcTimeEl = document.querySelector('#utc-time');
const timerEl1 = document.querySelector('#timer-1');
const timerEl2 = document.querySelector('#timer-2');
const timerEl3 = document.querySelector('#timer-3');
const main = () => {
// 本地时间
looper(() => { localTimeEl.textContent = getLocaleTimeString(); }, 1000);
// UTC 时间
looper(() => { utcTimeEl.textContent = getLocaleTimeString('UTC'); }, 1000);
// 每天
const timer1 = new CountdownTimer({
time: '04:00',
timeZone: 'UTC',
renderFn: (duration) => {
timerEl1.textContent = formatDuration(duration);
}
}).start();
// 下个星期日
const timer2 = new CountdownTimer({
time: '04:00',
timeZone: 'UTC',
dayOfWeek: 0,
renderFn: (duration) => {
timerEl2.textContent = formatDuration(duration);
}
}).start();
// 今天
const timer3 = new CountdownTimer({
time: '12:00',
timeZone: 'PDT',
isToday: true,
renderFn: (duration) => {
timerEl3.textContent = formatDuration(duration);
}
}).start();
};
const looper = (callback, ms) => {
setInterval(callback, ms);
callback();
};
const getLocaleTimeString = (timeZone) =>
new Date().toLocaleString('en-US', { timeZone });
const parseDuration = (duration) => {
duration = +duration;
const days = Math.floor(duration / 8.64e7);
duration %= 8.64e7;
const hours = Math.floor(duration / 3.6e6);
duration %= 3.6e6;;
const minutes = Math.floor(duration / 6e4);
duration %= 6e4;
const seconds = Math.floor(duration / 1e3);
return { days, hours, minutes, seconds };
}
const applyUnit = (value, singular, plural) =>
value > 0
? value + (value === 1 ? ` ${singular}` : ` ${plural}`)
: null;
const formatDurationFull = (duration) => {
const { days, hours, minutes, seconds } = parseDuration(duration);
return [
applyUnit(days, 'day', 'days'),
applyUnit(hours, 'hour', 'hours'),
applyUnit(minutes, 'minute', 'minutes'),
applyUnit(seconds, 'second', 'seconds'),
].filter(v => v).join(', ');
};
const formatDurationSimple = (duration) => {
const { days, hours, minutes, seconds } = parseDuration(duration);
return [ days, hours, minutes, seconds ]
.map(v => v.toString().padStart(2, '0')).join(':');
};
const formatDuration = (duration) =>
duration > 0
? `${formatDurationSimple(duration)} (${formatDurationFull(duration)})`
: 'Expired';
const getDateNextWeek = (date, dayOfWeek = 0) => {
const currentDate = new Date(date);
currentDate.setDate(currentDate.getDate() + (7 - currentDate.getDay() + dayOfWeek) % 7);
return currentDate;
};
const getTomorrow = (date) => {
const currentDate = new Date(date);
currentDate.setDate(currentDate.getDate() + 1);
return currentDate;
};
class CountdownTimer {
constructor(options) {
const opts = { ...options };
this.time = opts.time;
this.timeZone = opts.timeZone;
this.dayOfWeek = opts.dayOfWeek;
this.renderFn = opts.renderFn;
this.isToday = opts.isToday ?? false;
this.targetDate = this.computeTargetDate();
}
start() {
this.stop();
this.update();
this.intervalId = setInterval(this.update.bind(this), 1000);
return this;
}
stop() {
if (this.intervalId) {
clearInterval(this.intervalId);
}
this.intervalId = undefined;
return this;
}
update() {
this.renderFn(this.targetDate - new Date());
}
// 2019-01-01T00:00:00.000+00:00
computeTargetDate() {
const now = new Date();
const timeTokens = this.time.split(':').map(value => +value);
const futureHour = timeTokens[0] ?? 0;
const futureMinute = timeTokens[1] ?? 0;
const futureSecond = timeTokens[2] ?? 0;
const timeZone = this.parseTimeZone(this.timeZone);
let targetDate;
if (this.isToday) {
targetDate = now;
} else {
if (this.dayOfWeek === undefined) {
targetDate = getTomorrow(now);
} else {
targetDate = getDateNextWeek(now, this.dayOfWeek);
}
}
const y = targetDate.getUTCFullYear();
const m = (targetDate.getUTCMonth() + 1).toString().padStart(2, '0');
const d = targetDate.getUTCDate().toString().padStart(2, '0');
const H = futureHour.toString().padStart(2, '0');
const M = futureMinute.toString().padStart(2, '0');
const s = futureSecond.toString().padStart(2, '0');
const ts = `${y}-${m}-${d}T${H}:${M}:${s}${timeZone}`;
console.log(`Countdown target date: ${ts}`);
return Date.parse(ts);
}
parseTimeZone(timeZone) {
const offsetMinutes = this.timeZoneToMinutes(timeZone);
if (offsetMinutes == null) return '';
const sign = offsetMinutes < 0 ? '-' : '+';
const h = Math.abs(offsetMinutes / 60).toString().padStart(2, '0');
const m = Math.abs(offsetMinutes % 60).toString().padStart(2, '0');
return `${sign}${h}${m}`;
}
timeZoneToMinutes(timeZone) {
switch (timeZone) {
case 'UTC':
case 'GMT':
return 0;
case 'EDT': return -240;
case 'EST': return -300;
case 'CDT': return -300;
case 'CST': return -360;
case 'MDT': return -360;
case 'MST': return -420;
case 'PDT': return -420;
case 'PST': return -480;
default:
return null;
}
}
}
main();
这段代码创建了一个计时器类(CountdownTimer),并使用了面向对象编程的思想。它包含了计时器的各种功能,如开始计时(start)、停止计时(stop)、更新计时(update)等。你可以根据需要调整代码中的参数和函数,以满足你的需求。
英文:
You could try an OOP approach by creating a timer class. You would only need to compute the target date once. The timer will call the render function on an interval.
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
const localTimeEl = document.querySelector('#local-time');
const utcTimeEl = document.querySelector('#utc-time');
const timerEl1 = document.querySelector('#timer-1');
const timerEl2 = document.querySelector('#timer-2');
const timerEl3 = document.querySelector('#timer-3');
const main = () => {
// Local Time
looper(() => { localTimeEl.textContent = getLocaleTimeString(); }, 1000);
// UTC Time
looper(() => { utcTimeEl.textContent = getLocaleTimeString('UTC'); }, 1000);
// Every day
const timer1 = new CountdownTimer({
time: '04:00',
timeZone: 'UTC',
renderFn: (duration) => {
timerEl1.textContent = formatDuration(duration);
}
}).start();
// Next Sunday
const timer2 = new CountdownTimer({
time: '04:00',
timeZone: 'UTC',
dayOfWeek: 0,
renderFn: (duration) => {
timerEl2.textContent = formatDuration(duration);
}
}).start();
// Today
const timer3 = new CountdownTimer({
time: '12:00',
timeZone: 'PDT',
isToday: true,
renderFn: (duration) => {
timerEl3.textContent = formatDuration(duration);
}
}).start();
};
const looper = (callback, ms) => {
setInterval(callback, ms);
callback();
};
const getLocaleTimeString = (timeZone) =>
new Date().toLocaleString('en-US', { timeZone });
const parseDuration = (duration) => {
duration = +duration;
const days = Math.floor(duration / 8.64e7);
duration %= 8.64e7;
const hours = Math.floor(duration / 3.6e6);
duration %= 3.6e6;;
const minutes = Math.floor(duration / 6e4);
duration %= 6e4;
const seconds = Math.floor(duration / 1e3);
return { days, hours, minutes, seconds };
}
const applyUnit = (value, singular, plural) =>
value > 0
? value + (value === 1 ? ` ${singular}` : ` ${plural}`)
: null;
const formatDurationFull = (duration) => {
const { days, hours, minutes, seconds } = parseDuration(duration);
return [
applyUnit(days, 'day', 'days'),
applyUnit(hours, 'hour', 'hours'),
applyUnit(minutes, 'minute', 'minutes'),
applyUnit(seconds, 'second', 'seconds'),
].filter(v => v).join(', ');
};
const formatDurationSimple = (duration) => {
const { days, hours, minutes, seconds } = parseDuration(duration);
return [ days, hours, minutes, seconds ]
.map(v => v.toString().padStart(2, '0')).join(':');
};
const formatDuration = (duration) =>
duration > 0
? `${formatDurationSimple(duration)} (${formatDurationFull(duration)})`
: 'Expired';
const getDateNextWeek = (date, dayOfWeek = 0) => {
const currentDate = new Date(date);
currentDate.setDate(currentDate.getDate() + (7 - currentDate.getDay() + dayOfWeek) % 7);
return currentDate;
};
const getTomorrow = (date) => {
const currentDate = new Date(date);
currentDate.setDate(currentDate.getDate() + 1);
return currentDate;
};
class CountdownTimer {
constructor(options) {
const opts = { ...options };
this.time = opts.time;
this.timeZone = opts.timeZone;
this.dayOfWeek = opts.dayOfWeek;
this.renderFn = opts.renderFn;
this.isToday = opts.isToday ?? false;
this.targetDate = this.computeTargetDate();
}
start() {
this.stop();
this.update();
this.intervalId = setInterval(this.update.bind(this), 1000);
return this;
}
stop() {
if (this.intervalId) {
clearInterval(this.intervalId);
}
this.intervalId = undefined;
return this;
}
update() {
this.renderFn(this.targetDate - new Date());
}
// 2019-01-01T00:00:00.000+00:00
computeTargetDate() {
const now = new Date();
const timeTokens = this.time.split(':').map(value => +value);
const futureHour = timeTokens[0] ?? 0;
const futureMinute = timeTokens[1] ?? 0;
const futureSecond = timeTokens[2] ?? 0;
const timeZone = this.parseTimeZone(this.timeZone);
let targetDate;
if (this.isToday) {
targetDate = now;
} else {
if (this.dayOfWeek === undefined) {
targetDate = getTomorrow(now);
} else {
targetDate = getDateNextWeek(now, this.dayOfWeek);
}
}
const y = targetDate.getUTCFullYear();
const m = (targetDate.getUTCMonth() + 1).toString().padStart(2, '0');
const d = targetDate.getUTCDate().toString().padStart(2, '0');
const H = futureHour.toString().padStart(2, '0');
const M = futureMinute.toString().padStart(2, '0');
const s = futureSecond.toString().padStart(2, '0');
const ts = `${y}-${m}-${d}T${H}:${M}:${s}${timeZone}`;
console.log(`Countdown target date: ${ts}`);
return Date.parse(ts);
}
parseTimeZone(timeZone) {
const offsetMinutes = this.timeZoneToMinutes(timeZone);
if (offsetMinutes == null) return '';
const sign = offsetMinutes < 0 ? '-' : '+';
const h = Math.abs(offsetMinutes / 60).toString().padStart(2, '0');
const m = Math.abs(offsetMinutes % 60).toString().padStart(2, '0');
return `${sign}${h}${m}`;
}
timeZoneToMinutes(timeZone) {
switch (timeZone) {
case 'UTC':
case 'GMT':
return 0;
case 'EDT': return -240;
case 'EST': return -300;
case 'CDT': return -300;
case 'CST': return -360;
case 'MDT': return -360;
case 'MST': return -420;
case 'PDT': return -420;
case 'PST': return -480;
default:
return null;
}
}
}
main();
<!-- language: lang-css -->
h2 { margin: 0; padding: 0; margin-top: 0.25rem; font-size: 1.25rem; }
.grid { display: grid; grid-template-rows: repeat(2, auto); grid-auto-flow: column; }
<!-- language: lang-html -->
<div class="grid">
<h2>Local Time</h2>
<div id="local-time"></div>
<h2>UTC Time</h2>
<div id="utc-time"></div>
</div>
<h2>Tomorrow @ 4am UTC</h2>
<div id="timer-1"></div>
<h2>Sunday @ 4am UTC</h2>
<div id="timer-2"></div>
<h2>Today @ 12pm PDT (-07:00)</h2>
<div id="timer-3"></div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论