Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
189 views
in Technique[技术] by (71.8m points)

javascript - 没有正确计算停机时间(Not counting down time correctly)

I am creating a countdown website.(我正在创建一个倒计时网站。)

I want it to count down from the current time the my celebration date 2019-11-29 00:00:00 .(我希望它从当前时间2019-11-29 00:00:00我的庆祝活动日期2019-11-29 00:00:00 。) I want the timezone to be in Australia Brisbane time zone.(我希望时区在澳大利亚布里斯班时区。) However, it seems to be that it keeps calculating the amount of time left till my celebration date wrong.(但是,似乎它一直在计算直到我的庆祝日期不对的时间。) Could someone tell me what I did wrong?(有人可以告诉我我做错了什么吗?) And once the time hits 0, how can I get rid of the countdown and replace it with <a href="party.html">Its celebration time</a>(时间到了0,我该如何摆脱倒计时,而将其替换为<a href="party.html">Its celebration time</a>)

 function dateDiff(a, b) { // Some utility functions: const getSecs = dt => (dt.getHours() * 24 + dt.getMinutes()) * 60 + dt.getSeconds(); const getMonths = dt => dt.getFullYear() * 12 + dt.getMonth(); // 0. Convert to new date objects to avoid side effects a = new Date(a); b = new Date(b); if (a > b) [a, b] = [b, a]; // Swap into order // 1. Get difference in number of seconds during the day: let diff = getSecs(b) - getSecs(a); if (diff < 0) { b.setDate(b.getDate()-1); // go back one day diff += 24*60*60; // compensate with the equivalent of one day } // 2. Get difference in number of days of the month let days = b.getDate() - a.getDate(); if (days < 0) { b.setDate(0); // go back to (last day of) previous month days += b.getDate(); // compensate with the equivalent of one month } // 3. Get difference in number of months const months = getMonths(b) - getMonths(a); return { years: Math.floor(months/12), months: months % 12, days, hours: Math.floor(diff/3600), minutes: Math.floor(diff/60) % 24, seconds: diff % 60 }; } // Date to start on var celebrationDate = new Date("2019-11-29 00:00:00").toLocaleString("en-US", {timeZone: "Australia/Brisbane"}); // Update the count every 1 second !function refresh () { const diff = dateDiff(new Date().toLocaleString("en-US", {timeZone: "Australia/Brisbane"}), celebrationDate); document.getElementById("day-val").innerHTML = diff[Object.keys(diff)[2]]; document.getElementById("hour-val").innerHTML = diff[Object.keys(diff)[3]]; document.getElementById("min-val").innerHTML = diff[Object.keys(diff)[4]]; document.getElementById("sec-val").innerHTML = diff[Object.keys(diff)[5]]; setTimeout(refresh, 1000) }() 
 <div id="day-val"></div><div>Days</div><br> <div id="hour-val"></div><div>Hours</div><br> <div id="min-val"></div><div>Minutes</div><br> <div id="sec-val"></div><div>Seconds</div> 

  ask by Jackie translate from so


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Solution with plain javascript:(使用纯JavaScript的解决方案:)

  1. Get the clients time zone offset(获取客户的时区偏移量)
  2. Calculate the diff between client offset and "Australian/Brisbane" offset(计算client offset"Australian/Brisbane" offset之间的差异)
  3. Calculate time left by targetDate - currentDate - offsetDiff(计算targetDate - currentDate - offsetDiff)
  4. Format the result to display it(格式化结果以显示它)

Example:(例:)

const minToMS = min => min * 60 * 1000

const getCountDownFromMS = diff => {
    const milliseconds = diff % 1000
    diff = (diff - milliseconds) / 1000
    const seconds = diff % 60
    diff = (diff - seconds) / 60
    const minutes = diff % 60
    diff = (diff - minutes) / 60
    const hours = diff % 24
    diff = (diff - hours) / 24
    const days = diff
    return {
        days,
        hours,
        minutes,
        seconds,
        milliseconds
    }
}

const targetDate = new Date('2019-11-29 00:00:00')
// Getting offset with getTimezoneOffset is not reliable, using a database to get time zone offset is needed, like IANA Time Zone Database.
// moment.js internally uses IANA db 
const tzOffset = targetDate.getTimezoneOffset() // Client browsers timezone offset in minutes
const target_tzOffset = -600 // Australia Brisbane timezone offset in minutes
const offset = minToMS(tzOffset - target_tzOffset)
const msLeft = targetDate - new Date() - offset
const result = getCountDownFromMS(msLeft)

You should also check moment.js as it has many useful features.(您还应该检查一下moment.js,因为它具有许多有用的功能。)

Example with moment.js:(使用moment.js的示例:)

const now = moment()
const target = moment.tz('2019-11-29 00:00:00', 'Australia/Brisbane')
const result = moment.duration(target.diff(now))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...