Count down and reset count with javascript - javascript

I want to show a countdown on my website. for all users but I don't want to use any backend language.
Countdown is starting from 20 and after each 1min I am decreasing number by 1. Means after 2mins the value will be 18 and when it reachs at 3 the number should reset to 20. I use the time difference to do that it count down correctly but reseting is not working. I have two functions
function change_html() {
var start_number = 20;
var start = new Date("November 11, 2020 00:00:00"); // This will get the all milisec
var end = new Date(); // This will get the all milisec of current
var final = (get_difference(start,end)); // This will return all the mins passed
var new_start = (final/20); // This will get how many 20 are passed
var new_final = new_start.toString();
new_final = new_final.split(".");
var final_to_show = new_start-parseInt(new_final[0]);
final_to_show = final_to_show*20; // This will get how many numbers are remain to complete 20
final_to_show = Math.round(((20)-final_to_show));
document.getElementById('html_element').innerHTML = final_to_show;
}
And second for converting milisec to mins
function get_difference(start,end) {
var difference =((end.getTime() - start.getTime()) / 1000)/60;
return Math.abs(Math.round(difference));
}
I didn't want to reset the countdown on reload and the loop is endless.
I don't understand what to do with reset because it is not based on any static value it will be done in jQuery and Javascript. Please help me with this or suggest me to do it with another way.

You just need to use a setInterval method
the most complicated was to set your countdown of 17 minutes in offset of 3 points, with a first start at 20.
...and you should have a look about how the modulo works in math
const showElement = document.getElementById('html_element')
, one_Sec = 1000
, one_Min = one_Sec * 60
, countMax = 20
, countMin = 3
, countRange = countMax - countMin +1
, startDateT = (new Date("November 11, 2020 00:00:00")).getTime()
, timeNowDiff = () => Math.floor(Math.abs(((new Date()).getTime() -startDateT) / one_Min ))
;
showElement.textContent = countMax -(timeNowDiff() % countRange)
setInterval(()=>
{
showElement.textContent = countMax -(timeNowDiff() % countRange)
}
, one_Sec *10); // check display change every 10 seconds....
changing every minutes : <span id="html_element" style="color:red"></span> until 3

Related

Get remaining time with an array for opening hours

I'm trying to create a countdown to get the remaining time before my shop will close
// My array for the opening hours :
var openTime = [
{ open : 9, close : 17},
{ open: 9, close : 18 },
{ open: 9, close : 18 },
{ open: 9, close : 18 },
{ open: 9, close : 18 },
{ open: 9, close : 18 },
{ open: 10, close : 16.5 }
]
var current = new Date();
var day = current.getDay();
var currentTime = current.getHours() + (current.getMinutes() / 60);
var remainTime = 0;
if (openTime[day].open >= 0 && openTime[day].open < currentTime && openTime[day].close >
currentTime) {
remainTime = (openTime[day].close - currentTime).toFixed(2)
}
console.log("the shop will close in %s hours", remainTime);
But I have a problem with this line :
var currentTime = current.getHours() + (current.getMinutes()/60);
Because when I execute the code, for exemple, actually it's 17h22, the code give me on my debugger that current time equal to 17.36 ?
There is something wrong with the line, because it's give me the wrong remaining time...
0.36 of an hour (a decimal magnitude) equals 21.6 (≈22) minutes.
It's simple to convert decimal to minutes: 60*decimal. Or (60*decimal).toFixed(0) or (60*decimal).round() if you want a round number.
Also, remember that JS uses the device's time. Today most devices sync their time, but if you don't want to rely on it, you should bring the time from your server (ie. storing it in a JS variable at preprocessing time, like var time=<?=time()?>;).
If you want current time as string you have to:
var currentTime = current.getHours() + ":" + (current.getMinutes() / 60);
but thats not what you want I guess. You get of coures 17.36 because 17:22 converted to decimal base 10 instead of 60 minutes gives this value (22 min /60 =0.363636 rounded two digits 0.36). If you want to have the timer working you convert either back the decimal part by *60 to easy find it. Use:
var decimalPart = remainTime % 1;
var remainTimeHours = remainTime - decimalPart;
var remainTimeMin = decimalPart * 60;
Of course you can simplify it - just to show the logic
-in your closing time you use already 16.5 means 16:30 or should it be 16:50 -> then 16.83
or preferred seperate logic for hours and minutes not converted to decimal using even seconds if needed.

Converting to duration from milliseconds

I am trying to convert time duration from the format of mm:ss.mss to entirely milliseconds and back.
I've already have a working function for converting from milliseconds to duration but I cannot seem to get it the other way around.
Lets say for instance that I have the duration 32:29.060, I want to convert it to milliseconds. For that I use this function:
function millisecondsToTime(ms, digits) {
digits = digits || 12;
return new Date(ms).toISOString().slice(23-digits, -1);
}
var a = millisecondsToTime(5549060, 9);
but whenever I try to convert back to time duration, I fail. I've tried parsing individually the minutes, seconds and milliseconds but it doesn't seem to work.
Here is the code that I've used for it:
var firstSplit = a.split(':')
var minutes = firstSplit[0]; //1
var secondSplit = firstSplit[1].split('.');
var seconds = secondSplit[0]; //2
var millisec = secondSplit[1]; //3
var conversion = ((+minutes) * 60 + (+seconds) * 60 + (+millisec))*1000;
I have an input bar which takes the format of mm:ss.mss and I need to convert it to milliseconds. How can I do that?
you can just return a
new Date(ms)
to get a date from ms.
And to get the same date as ms,
date.getTime() // returns ms from date object
Full example:
const ms = 5549060
const date = new Date(ms) // get a date from ms
console.log(date.getTime) // logs 5569060
If your input is a string in the format of mm:ss.mss, and you want to get a date from it, you can use moment.
const moment = require('moment')
const date = moment('22:15.143', 'mm:ss.SSS') // get date from pre specified format
You can use the string methods indexOf() and substr() to get the individual numbers out of your string and calculate the time accordingly.
I'm afraid though your millisecondsToTime() function isn't working properly.
5549060 milliseconds are roughly 92 minutes and it's returning 32:29.060
function backToTime(time) {
var index = time.indexOf(":");
var minutes = time.substr(0, index);
var seconds = time.substr(index + 1, time.indexOf(".") - (index + 1));
var milliseconds = time.substr(time.indexOf(".") + 1, time.length);
return parseInt(minutes * 60 * 1000) + parseInt(seconds * 1000) + parseInt(milliseconds);
}
console.log(backToTime("32:29.060"));
Your conversion to milliseconds is not working, this is basic math approach to both conversions:
let input = 5549060
//toDuration
let seconds = Math.floor(input / 1000);
let ms = input - seconds*1000;
let m = Math.floor(seconds / 60);
let s = seconds - m*60;
duration = m + ":" + s + "." + ms
console.log(duration)
//toMilliseconds
let holder = duration.split(":");
m = parseInt(holder[0]);
holder = holder[1].split(".");
s = parseInt(holder[0]);
ms = parseInt(holder[1]);
milliseconds = (m*60 + s)*1000 + ms
console.log(milliseconds)
If needed add check for ms length to add 0s, if you need it to have length of 3
I think your milliseconds to duration converter will be broken for durations above 60 minutes. This is because using Date the minutes field will wrap over into the minutes after 59 seconds have passed. If you want to get good support for values beyond 59 in your first field, I think maybe moving to a regex-based parser and using multiplication and addition, division and modulo to extract and reduce the fields manually might be nice. Something like this maybe:
var duration = ms => `${(ms / 60000) | 0}`.padStart(2, '0') + `:` + `${ms % 60000 / 1000 | 0}`.padStart(2, '0') + `.` + `${ms % 1000}`.padStart(3, '0')
var millisec = durat => (match => match && Number(match[1]) * 60000 + Number(match[2]) * 1000 + Number(match[3]))(/^([0-9]+)\:([0-5][0-9])\.([0-9]{3})$/.exec(durat))
You can see given the input 5549060, this function provides output 92:29.60, which is exactly 60 seconds greater than your own, and I believe to be correct. Maybe it's intentional for your usecase, but I can't imagine that being so desirable generally...

Making a min:sec counter using javascript

I am trying to make a small question/answer quiz game using react, and I want to show a timer that counts down every second. Each game will last 10, 15, or 30 minutes at most, so I want to show a timer that updates every second in the bottom of the screen (in big font, of course!), something like 15:00, 14:59, 14:58, and so on until it hits 00:00.
So, given a start time such as 2016-04-25T08:00:00Z, and an end time after adding 15 min of 2016-04-25T08:15:00Z, I want to start the countdown.
My issue is that I am not understanding how to use setIntervals to keep calling my method to find the remaining time.
timeLeft = Math.round(timeLeft/1000) * 1000;
const timer = new Date(timeLeft);
return timer.getUTCMinutes() + ':' + timer.getUTCSeconds();
EDIT: You've edited your question. You will need the time padding, and the method below will be faster than what you are using, but to answer your question about setInterval:
First, define your function to run your timer and decrement each time it's called:
var timeLeft; // this is the time left
var elem; // DOM element where your timer text goes
var interval = null; // the interval pointer will be stored in this variable
function tick() {
timeLeft = Math.round(timeLeft / 1000) * 1000;
const timer = new Date(timeLeft);
var time = timer.getUTCMinutes() + ':' + timer.getUTCSeconds();
elem.innerHTML = time;
timeLeft -= 1000; // decrement one second
if (timeLeft < 0) {
clearInterval(interval);
}
}
interval = setInterval(tick, 1000);
OG Answer:
No, I do not believe there is a built-in way to display time differences.
Let's say you have two date objects:
var start = Date.now();
var end = Date.now() + 15 * 60 * 1000; // 15 minutes
Then you can subtract the two Date objects to get a number of milliseconds between them:
var diff = (end - start) / 1000; // difference in seconds
To get the number of minutes, you take diff and divide it by 60 and floor that result:
var minutes = Math.floor(diff / 60);
To get the number of seconds, you take the modulus to get the remainder after the minutes are removed:
var seconds = diff % 60;
But you want these two padded by zeros, so to do that, you convert to Strings and check if they are two characters long. If not, you prepend a zero:
// assumes num is a whole number
function pad2Digits(num) {
var str = num.toString();
if (str.length === 1) {
str = '0' + str;
}
return str;
}
var time = pad2Digits(minutes) + ':' + pad2Digits(seconds);
Now you have the time in minutes and seconds.

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");

Executing code inside setInterval function only once per few seconds

I'm working on a simple project that is HTML and Javascript; and I have a problem with my timer.
I'm calculating the seconds between two Date() objects; and every 2 seconds, I want to get a new random number. I have a setInterval that runs every 100 ms and when I get past the 2 second mark, the code inside the if statement should run.
So my question is:
How can I make sure the code execute only once per 2 seconds in an if statement that is inside a setInterval() that runs every 100 ms?
Here is the code:
var startTime = new Date();
var endTime = new Date();
var randomNumber = 0;
var gameTimer = setInterval(function(){
//calculate seconds;
var secondsPassed = Math.round( (endTime - startTime) / 1000 );
if(modulo(secondsPassed,2) == 0){
//when the "gate" is open this keep executing every 100 mili seconds.
//but i want it to execute only once every 2 seconds.
randomNumber = Math.floor(Math.random()*lanes.length);
$(lanes[randomNumber]).append(box);
}
endTime = new Date();
}, 100);
var modulo = function (n, m) {
var remain = n % m;
return Math.floor(remain >= 0 ? remain : remain + m);
};
I think you are asking for a double-interval timer.
var interval = 100, beat = 2000, ticks = 0;
var timer = setInterval(function(){
runsEvery100ms(); // ««« Code here runs every 100 ms.
if (ticks > 0 && ticks % beat === 0) {
runsEvery2000ms(); // ««« Code here runs every 2000 ms.
ticks = 0;
}
ticks += interval;
}, interval);
Demo Fiddle here.

Categories