Ensure JavaScript countdown clock does not count beyond 59 seconds/minutes - javascript

My apologies if a similar question has been asked before - I could not find it on SO.
I've constructed a countdown clock in pure JS that will countdown opening times (different for Fri,Sat,Sund and the remaining weekdays). I have also offset the AEST timezone so that the time is constant no matter what internet connected device you are accessing in whatever timezone.
Works great! Although I'm working to streamline the code of course. Small bug I noticed this morning is that it likes to count down from 60secs and 60min instead of having them converted to the next unit of time up. (i.e. when the countdown started this morning at 10am to count down until 5pm, it began with 6 hours, 60 mins - definitely should be 7 hours!).
Anwyay, this is my code:
function ShowTime() {
//access system clock and get the time
var aest = new Date();
var localTime = aest.getTime();
//obtain local UTC offset and convert to msec
var localOffset = aest.getTimezoneOffset()*60000;
//Get total UTC time in msec
var utc = localTime + localOffset;
//obtain and add destination UTC time offset (Brisbane, Australia +10)
var offset = 10;
var brisbane = utc + (3600000*offset);
var brisDay = new Date(brisbane);
brisDay = brisDay.getDay();
//Set weekend days with different opening hours
//Set numbers representing weekend days - 0 for Sunday, 6 for Saturday
if (brisDay===0 || brisDay===5 || brisDay===6) {
var hoursBase = 16
var hoursBefore = 6;
}
else {
var hoursBase = 19;
var hoursBefore = 9;
}
//convert msec value (with timezone offset) to datetime string variables
var consTime = new Date(brisbane);
var brisHours = hoursBase-consTime.getHours();
var brisMinutes = 60-consTime.getMinutes();
var brisSec = 60-consTime.getSeconds();
//complete string for offset AEST local time
//show CLOSED message if past closing time
if (brisHours<0 || brisHours>hoursBefore) {
var timeLeft = "<strong style='background-image:url()'>The SLQ building is currently closed.</strong>";
} else if (brisHours<1 || brisHours>hoursBefore) {
var timeLeft = "SLQ will be open for another<br /><strong>" +brisHours+' hrs '+brisMinutes+' min '+brisSec+' sec'+ "</strong> today";
} else if (brisHours<2 || brisHours>hoursBefore) {
var timeLeft = "SLQ will be open for another<br /><strong>" +brisHours+' hrs '+brisMinutes+' min '+brisSec+' sec'+ "</strong> today";
} else if (brisHours<3 || brisHours>hoursBefore) {
var timeLeft = "SLQ will be open for another<br /><strong>" +brisHours+' hrs '+brisMinutes+' min '+brisSec+' sec'+ "</strong> today";
}
else {
var timeLeft = "SLQ will be open for another<br /><strong>" +brisHours+' hrs '+brisMinutes+' min '+brisSec+' sec'+ "</strong> today";
}
//output adjusted time into page
document.getElementById("countdown").innerHTML = timeLeft;
}
//Setup variable to update on setInterval function every 1000 milliseconds
var countdown = setInterval(ShowTime ,1000);
and here is a working JS Fiddle: https://jsfiddle.net/coolwebs/pbno1jhe/1/
I have looked into the problem and it appears as though my issue lies in the fact that I have set the
var brisMinutes = 60-consTime.getMinutes();
var brisSec = 60-consTime.getSeconds();
When I change these numeric values to be "59" - like I have in the provided JS Fiddle - it seems to resolve the issue but also appears to be slightly out of sync with the computer clock.
I think I have approached it incorrectly, so could someone please give me their opinion on the matter?

Related

Date and Time Difference and Average time

I have two times (basically start time and end time). Also, I have the number of questions played by the user. I wanna know the average time user spent for each question.
//startGameTime: 2019-07-27T07:58:42.000Z
//endGameTime: 2019-07-27T07:59:57.000Z
function averageQuestionTime(startGameTime, endGameTime, totalNumberOfQuestions) {
var d1 = new Date(startGameTime);
var d2 = new Date(endGameTime);
var d1msecs = new Date(d1).getTime(); // get milliseconds
var d2msecs = new Date(d2).getTime(); // get milliseconds
var avgTime = (d1msecs + d2msecs) / totalNumberOfQuestions;
var date = new Date(avgTime);
var hour = date.getUTCHours();
var min = date.getUTCMinutes();
var sec = date.getUTCSeconds();
var day = date.getUTCDate() - 1;
return (day + ":" + hour + ":" + min + ":" + sec)
}
I understand my logic is completely flawed as the units for date and time and nos of questions are different. What is the best way to achieve the result ?
There are good libraries which prevent the users from having to reinvent the wheel every time they want to manipulate date/time in Node.
Obtaining time difference is pretty simple (I can see you are doing it correctly to obtain the difference in milliseconds) and libraries make them even simpler.
See how simple it is using momentJS
var moment = require('moment');
var startDate = moment('2019-7-24 00:00:00', 'YYYY-M-DD HH:mm:ss');
var endDate = moment('2019-7-24 05:27:31', 'YYYY-M-DD HH:mm:ss');
var diffSeconds = endDate.diff(startDate, 'seconds');
var diffHours endDate.diff(startDate, 'seconds');
console.log(`Avg in secs: ${diffSeconds / totalNumberOfQuestions}`);
console.log(`Avg in secs: ${diffHours/ totalNumberOfQuestions}`);

Jquery timer with UTC offset

function getMinutesUntilNextHour() {
var now = new Date();
var hours = now.getUTCHours();
var mins = now.getMinutes();
var secs = now.getSeconds();
// Compute time remaining per unit
var cur_hours = 23 - hours;
var cur_mins = 60 - mins;
var cur_secs = 60 - secs;
// Correct zero padding of hours if needed
if (cur_hours < 10) {
cur_hours = '0' + cur_hours;
}
// Correct zero padding of minutes if needed
if (cur_mins < 10) {
cur_mins = '0' + cur_mins;
Here’s the code for a simple 24 hour countdown timer that resets again after each 24 hours but when I add, say, 11- hours in the compute time remaining section it occasionally throws a negative time (in hours) at me depending on the current UTC time. I’d just like the 24 hour period to start from a different time /time zone. All help greatly appreciated
You might be looking at this backwards :-) Why don't you create a Date object for midnight, then subtract current time from it. This example works for the local timezone, but you could easily adapt it for UTC, or another timezone.
// We're going to use Vue to update the page each time our counter changes.
// You could also do this old style, updating the DOM directly.
// vueStore is just a global variable that will contain the current time,
// and the function to periodically update it.
var vueStore = {
now: new Date(),
countdown(){
vueStore.now = new Date();
window.setTimeout(() => {this.countdown(); }, 1000);
}
};
vueStore.countdown();
var vm = new Vue({
el: "#vueRoot",
data: { vueStore: vueStore },
computed: {
timeTilMidnight() {
var midnightTonight = new Date(this.vueStore.now.getYear(), this.vueStore.now.getMonth(), this.vueStore.now.getDay() + 1);
var timeToMidnight = midnightTonight.getTime() - this.vueStore.now.getTime();
return new Date(timeToMidnight).toLocaleTimeString([], {
timeZone: "UTC"
});
}
}
});
<script src="https://unpkg.com/vue#2.5.17/dist/vue.js"></script>
<div id="vueRoot">
<h1>{{timeTilMidnight}}</h1>
</div>

Real Time decreasing value in php

I need some advice and logic in my problem.
So, I have an entrydate, from database, then the running current date, and a value of 10(double type in database). So, I know how to calculate the diff of the entrydate and current date, right. So I convert it to seconds then to a number(9.23165).
|Entry |Current Date|Diff(in number)|
|2:00:00 PM |2:30:00 PM | 5.00(Sample)|(First User)
So basically, as current date goes on, can PHP show the deduction on real time? Or I need to refresh? What I need is for it to display the deduction without refreshing. So basically, I need to know what I have to do. Maybe javascipt and ajax?
What you would need are a few Javascript/jQuery functions to update the browser in real time.
var myTimer;
var startTime;
function startTimer() {
stopTimer(); // Reset
startTime = new Date(); // Save to calculate difference
myTimer = setInterval(clockTicking, 1000);
}
function stopTimer() {
clearInterval(myTimer);
}
function clockTicking() {
var now = new Date();
var timeDiff = new Date(now - startTime); // constructor uses UTC, so use UTC date functions from here on
var hours = (timeDiff.getUTCHours() < 10) ? '0' + timeDiff.getUTCHours() : timeDiff.getUTCHours();
var mins = (timeDiff.getUTCMinutes() < 10) ? '0' + timeDiff.getUTCMinutes() : timeDiff.getUTCMinutes();
var secs = (timeDiff.getUTCSeconds() < 10) ? '0' + timeDiff.getUTCSeconds() : timeDiff.getUTCSeconds();
$("<element-where-you-display>").html(hours + ':' + mins + ':' + secs);
}
In Javascript you can call startTimer() to kick it off.

Convert thousands of seconds to h:mm:ss in moment.js

I've been going through the docs and I'm not sure what I'm doing wrong. I need to convert 7200 to 2:00:00. Seems easy? Some attempts:
var duration = 7200;
var display = moment().seconds(duration).format("h:mm:ss");
and...
var duration = 7200;
var display = moment.duration(duration, "seconds"); //can't chain on a format method?
The format comes back correct but the numbers are all wrong. If I use a duration of Math.round(7025.526) or 7025.526 I get 9:19:06 back.
How can I convert seconds to h:mm:ss successfully?
When you use moment().seconds(duration) it will take the current date and time, and then set the seconds component to the value (spilling over into minutes and hours). If you try it at different times you will see that the result changes.
A duration object can't be formatted as a date, because it's simply not a date. It's a length of time without any defined starting or ending point.
To convert the seconds first create an empty moment object, which will be the current date and the time 0:00:00. Then you can set the seconds, which will spill over into minutes and hours.
You would want to use H rather than h to format the hours. That avoids getting times less than an hour as 12:nn:nn instead of 0:nn:nn:
var duration = 7200;
var display = moment({}).seconds(duration).format("H:mm:ss");
let duration = seconds;
let hours = duration/3600;
duration = duration % (3600);
let min = parseInt(duration/60);
duration = duration % (60);
let sec = parseInt(duration);
if (sec < 10) {
sec = `0${sec}`;
}
if (min < 10) {
min = `0${min}`;
}
if (parseInt(hours, 10) > 0) {
return (`${parseInt(hours, 10)} : ${min} : ${sec}`)
}
return (`${min} : ${sec}`)
You can do it manually by calculating hours minutes and seconds
Using the moment-duration-format plugin:
var s = moment.duration(ms).format("h:mm:ss");
Or, just using moment:
var d = moment.duration(ms);
var s = Math.floor(d.asHours()) + moment.utc(ms).format(":mm:ss");

Countdown changed by changing gmt of system(pc) clock

Hi guys need some help,
here is my code
function getCurrentDateByGMT(finalTimezone){
var now = new Date();
var localTime = now.getTime();
var finalGMT = now.getTimezoneOffset() - finalTimezone;
var localOffset = finalGMT * 60000; // where 60000 is equals to 1 min
return new Date(localTime + localOffset);
}
this function gets the current date by inputed gmt -480 where gmt + 8 multiplied by -60
but whenever i changed my computer timezone the countdown also changed.
after i refresh the browser it went back to normal countdown without changing the timezone.
i wonder why can someone help me with this ? thanks in advance and also for grammar correction you are welcome to edit this question thanks thanks.
also, can someone explain this to me thanks again
update :
okay here's my full code
function getTimeRemaining(endtime,gmt){
var t = Date.parse(endtime) - Date.parse(getCurrentDateByGMT(gmt));
var seconds = Math.floor( (t/1000) % 60 );
var minutes = Math.floor( (t/1000/60) % 60 );
var hours = Math.floor( (t/(1000*60*60)) % 24 );
var days = Math.floor( t/(1000*60*60*24) );
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(hour,minute,second,endtime,gmt){
var locHour = document.getElementById(hour);
var locMinute = document.getElementById(minute);
var locSecond = document.getElementById(second);
if(!endtime){
console.log(false);
}else{
function updateClock(){
var countDown = getTimeRemaining(endtime,gmt);
console.log(countDown);// here is the console that output the image above
if(countDown.total>=0){
locHour.innerHTML = ('0' + countDown.hours).slice(-2);
locMinute.innerHTML = ('0' + countDown.minutes).slice(-2);
locSecond.innerHTML = ('0' + countDown.seconds).slice(-2);
}else{
console.log("happend");
clearInterval(timeinterval);
initializeClock(hour,minute,second,generateTimerPerPeriod(),gmt);
}
}
updateClock(); // run function once at first to avoid delay
var timeinterval = setInterval(updateClock,1000);
}
}
function generateTimerPerPeriod(){
var schedule = [['00:00:00', '11:59:59'],['12:00:00', '15:59:59'],['16:00:00', '19:59:59'],['20:00:00', '23:59:59']];
var currentTime = getCurrentDateByGMT(getTimezone('+8'));
var currentPeriod = new Date(currentTime);
for(var timeCtr = 0; timeCtr < schedule.length ; timeCtr++){
var startDate = schedule[timeCtr][0].split(':');
var endDate = schedule[timeCtr][1].split(':');
if(currentTime > currentPeriod.setHours(startDate[0],startDate[1],startDate[2],0) && currentTime < currentPeriod.setHours(endDate[0],endDate[1],endDate[2],0)){
var periodDate = new Date(currentPeriod.setHours(endDate[0],endDate[1],endDate[2],0));
// console.log(" enddate " +periodDate);
return periodDate;
}
}
return false;
}
function getCurrentDateByGMT(finalTimezone){
var myOldDateObj = new Date();
var myTZO = -480;
var myNewDate=new Date(myOldDateObj.getTime() + (60000*(myOldDateObj.getTimezoneOffset()-myTZO)));
console.log(" newdate "+ myNewDate);
var now = new Date();
var localTime = now.getTime();
var finalGMT = now.getTimezoneOffset() - finalTimezone;
var localOffset = finalGMT * 60000; // where 60000 is equals to 1 min
return new Date(localTime + localOffset);
}
function getTimezone(timezone){
return timezone * (-60);
}
Update :
how about this one ?
function getCurrentTimeGMT8(){
var d = new Date();
utc = d.getTime() + (d.getTimezoneOffset() * 60000);
var now = new Date(utc + (3600000*8));
var hour = addZero(now.getHours());
var min = addZero(now.getMinutes());
var sec = addZero(now.getSeconds());
var tz = "GMT+8";
var time = hour +':'+ min +':'+ sec + " " + tz;
return time;
}
A few things:
The getTime function of the Date object always returns values in terms of UTC, so calling it localTime is incorrect. That means your finalGMT and localOffset values are also incorrect because you're assuming the localTime value has been adjusted for the local offset, and it hasn't. Your code should just be:
Any time you construct a new Date by changing the underlying timestamp (like you do with new Date(localTime + localOffset), and also when you create your myNewDate variable), you're not actually changing the time zone. You're just moving the Date to a different moment in time, which is probably not the one you intended. The Date object will still represent time in the current local time zone, and will still follow the DST transition rules for the current local time zone. If you intended it to represent some other time zone, that can get in the way.
Note that you can still calculate the UTC-based numeric timestamp from the current time via Date.now() (or via Date.UTC with user input values) and adding the desired offset. You just can't then take that timestamp and put it in a Date object unless you intend it to reflect the local time zone. If you need to know the year, month, day, hour, minute, second of that timestamp in any other time zone than the local zone, you'll need a library such as moment.js, or some advanced algorithms of your own.
You asked about changing the time zone in the OS. You should recognize that the effect of this is inconsistent across browsers, versions, and operating systems. Many browsers (such as Chrome) will not pick up the new time zone until the browser process is completely terminated and restarted. However, some browsers (such as IE) will update the time zone without requiring a restart. If you need the user's time zone offset, you shouldn't cache it.
Keep in mind that a number can only represent an offset. A time zone can have more than one offset, either due to daylight saving time, or due to changes over its history. Read "Time Zone != Offset" in the timezone tag wiki.
In your case, your countdown timer is working only with offsets. If that's your intent, then fine. You can certainly take a date, time, and offset as input values. Just don't assume that the current offset from new Date().getTimezoneOffset() will necessarily be the correct offset for ALL dates and times in the user's time zone.

Categories