Timer not working when using readline-sync (Javascript) - javascript

I am making a game that keeps track of the time you take to complete the game, however i realised that the timer does not continue when i am asking for input.I tried to wait 10 seconds before typing a input but after i input a value the time is 00:00.Must i create a separate file for the timer or is there a possible way for the timer to run.Please help thanks!
var readline = require('readline-sync');
seconds = 0;
minute = 0;
timer = setInterval(() => {
if (seconds == 60) {
seconds = 0;
minute++;
}
seconds++;
}, 1000);
var input = readline.question('Input:');
clearInterval(timer);
//String to show time
if (minute < 10 && seconds < 10)
time = '0' + minute + ':0' + seconds;
else if (minute < 10 && seconds >= 10)
time = '0' + minute + ':' + seconds;
else if (minute >= 10 && seconds < 10)
time = minute + ':0' + seconds;
else
time = minute + ':' + seconds;
console.log(time);

It is easier just to create a Date object with new Date() and substract it from another Date created after the user Input.
var dateStart = new Date();
var input = readline.question('Input:');
var difference = new Date() - dateStart(); // time elapsed in milliseconds
For more complex cases I'd recommend looking up the libraries moment.js or date-fns.

Related

My JavaScript clock widget crashes Firefox

I am a JavaScript noob and realise that I need assistance.
All I want is to show a simple real-time clock with the time and AM/PM in separate SPANs.
The issue is that if I keep the tab open for 20-40 minutes (varies depending on how many other tabs I have open), it crashes the tab with an out of memory error. I have only tested this on Firefox (72.0.2) for now.
Why is my code so awfully memory intensive? It usually starts at around 2.4MB and then gradually increases and exceeds 42MB, then drops again, increases again and repeats the cycle several times until the tab crashes.
I've read aboout Garbage Collection but have no idea about how it works or if it's related to this problem.
Note that I've tried swapping setInterval with setTimeout but it's the same result.
This is my JavaScript:
window.onload = function() {
clock();
function clock() {
var now = new Date();
var TwentyFourHour = now.getHours();
var hour = now.getHours();
var min = now.getMinutes();
var sec = now.getSeconds();
var mid = 'PM';
if (min < 10) {
min = "0" + min;
}
if (hour > 12) {
hour = hour - 12;
}
if (hour == 0) {
hour = 12;
}
if (TwentyFourHour < 12) {
mid = 'AM';
}
document.getElementById('time-core').innerHTML = hour + ':' + min;
setInterval(clock, 1000);
document.getElementById('time-suffix').innerHTML = mid;
setInterval(clock, 1000);
}
}
And this is my HTML:
<span class="show-time" id="time-core"></span><span class="show-time-suffix" id="time-suffix"></span>
Thank you!
As Andreas said in his comment:
Every call of clock() adds two new intervals that each will call clock(). So after the first round we then have two scheduled clock() calls, then 4, then 8, then ...
One way to solve that would be to remove the setInterval from inside the clock function, like the example below.
window.onload = function() {
clock(); // Run it first so we don't have to wait 1 second
setInterval(clock, 1000); // Updates the clock every second
function clock() {
var now = new Date();
var TwentyFourHour = now.getHours();
var hour = now.getHours();
var min = now.getMinutes();
var sec = now.getSeconds();
var mid = 'PM';
if (min < 10) {
min = "0" + min;
}
if (hour > 12) {
hour = hour - 12;
}
if (hour == 0) {
hour = 12;
}
if (TwentyFourHour < 12) {
mid = 'AM';
}
document.getElementById('time-core').innerHTML = hour + ':' + min;
document.getElementById('time-suffix').innerHTML = mid;
}
}

JavaScript Stopwatch - Trouble Displaying a Leading Digit

I've been trying to create a simple stopwatch script using JavaScript in order to display the number of seconds, minutes, and hours that have elapsed.
Ideally, I'd like to have the time displayed as follows:
hh:mm:ss
With JavaScript, I was unable to find a built-in way to format numbers such that they contain a leading zero if a number is only one digit in length. This is where my problem lies - the logic that I added to the script to add a leading "0" works for the seconds display, but not for the minutes or hours displays.
Instead of only adding a leading "0" and then the one-digit value, the code I wrote will add in a "0" for each iteration of the setInterval() function, creating a long string of "0"s and then the current minutes or hours values.
I'm having trouble understanding why that is happening for the minutes and hours sections, but not for the seconds section when the code being used is the same.
In theory, I know that I'm essentially just adding another "0" to a string that then gets displayed each time the setInterval() function executes, but I can't seem to figure out why that doesn't happen in the seconds section. And what's also interesting is that the leading "0"s don't start getting added until the timer reaches two seconds.
Please see below for the code that I wrote for this stopwatch script. I'd certainly appreciate any insight that anyone could provide to get this working as expected.
let seconds = 0;
let minutes = 0;
let hours = 0;
function stopWatch(){
//Increment seconds on each "tick" of the stopwatch
seconds++;
//Check if minutes or hours needs to be incremented (which should happen every 60 seconds or 60 minutes, resepctively)
if(seconds / 60 == 0){
seconds = 0;
minutes++;
if(minutes / 60 == 0){
minutes = 0;
hours++;
}
}
//If the number of elapsed seconds, minutes, or hours is less than 10, add a 0 to the front of the number.
if(seconds < 10){
seconds = "0" + seconds;
}
if(minutes < 10){
minutes = "0" + minutes;
}
if(hours < 10){
hours = "0" + hours;
}
//Print the results to the "display" div in the HTML
document.getElementById("display").innerHTML = hours + ":" + minutes + ":" + seconds;
}
//Run the stopWatch() function every 1000ms
window.setInterval(stopWatch, 1000);
<div id="display">00:00:00</div>
And for what it's worth, I kept the <script></script> tags in the HTML document for simplicity, but once I get it working, I'll likely move the script to its own script.js file and potentially add in some buttons to start, stop, and reset the stopwatch.
let seconds = 0;
let minutes = 0;
let hours = 0;
let seconds_string = "0";
let minutes_string = "0";
let hours_string = "0";
function stopWatch(){
//Increment seconds on each "tick" of the stopwatch
seconds++;
//Check if minutes or hours needs to be incremented (which should happen every 60 seconds or 60 minutes, resepctively)
if(seconds / 60 === 1){
seconds = 0;
minutes++;
if(minutes / 60 === 1){
minutes = 0;
hours++;
}
}
//If the number of elapsed seconds, minutes, or hours is less than 10, add a 0 to the front of the number.
if(seconds < 10){
seconds_string = "0" + seconds.toString();
} else {
seconds_string = seconds.toString();
}
if(minutes < 10){
minutes_string = "0" + minutes.toString();
} else {
minutes_string = minutes.toString();
}
if(hours < 10){
hours_string = "0" + hours.toString();
} else {
hours_string = hours.toString();
}
//Print the results to the "display" div in the HTML
document.getElementById("display").innerHTML = hours_string + ":" + minutes_string + ":" + seconds_string;
}
//Run the stopWatch() function every 1000ms
window.setInterval(stopWatch, 1000);
<div id="display">00:00:00</div>
When you do "0" + minutes (and seconds, and hours) those variables get automatically converted into a string, consisting of two characters, a zero and something else.
Since the variables carry through each iteration, the next time you are adding another "0" character to the beginning of the string, and so-on.
The reason it's not happening to seconds is because you are converting seconds BACK to an int at the beginning of the loop when you do seconds++. So it becomes a string, then an int, then a string, etc.
To see this in action, try this snippet:
var test = 1;
console.log( typeof test ); //outputs "number"
test = "0" + test;
console.log( typeof test ); //outputs "string"
test++;
console.log( typeof test); //outputs number
My suggestion would be to separate counting units from display units. See if minutes is less than 10, and if so set outputMinutes to "0" + minutes. Do the same for seconds and hours. Then you just change the outputMinutes, outputSeconds, and outputHours each time, while the actual minutes, seconds, and hours variables remain as integers.
Instead of test in the if if the value is less than 10, test the length of that value as a string, if it is less than 2 (which means any number less than 10 in this case), then you add another "0" as a string to the value;
Like below:
let seconds = 0;
let minutes = 0;
let hours = 0;
function stopWatch(){
seconds++;
if(seconds / 60 == 0){
seconds = 0;
minutes++;
if(minutes / 60 == 0){
minutes = 0;
hours++;
}
}
if(seconds.toString().length < 2){
seconds = "0" + seconds;
}
if(minutes.toString().length < 2){
minutes = "0" + minutes;
}
if(hours.toString().length < 2){
hours = "0" + hours;
}
document.getElementById("display").innerHTML = hours + ":" + minutes + ":" + seconds;
}
window.setInterval(stopWatch, 1000);
<div id="display">00:00:00</div>

Stopwatch in Javascript is slower than normal time

I want to make a stopwatch in JavaScript that could count milliseconds, seconds and minutes. This is what I have: (you can stop the timer by pressing space)
var counter = document.getElementsByTagName('h1')[0];
var miliseconds = 0;
var seconds = 0;
var minutes = 0;
function Add() {
miliseconds++;
if (miliseconds >= 99) {
miliseconds = 0;
seconds++;
if (seconds >= 59) {
seconds = 0;
minutes++;
}
}
counter.textContent = (minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") + ":" +
(seconds ? (seconds > 9 ? seconds : "0" + seconds) : "00") + ":" +
(miliseconds ? (miliseconds > 9 ? miliseconds : "0" + miliseconds) : "00");
Timer();
}
function Timer() {
t = setTimeout(Add, 10);
}
Timer();
document.addEventListener("keypress", function(e) {
if (e.keyCode === 32) {
clearTimeout(t);
}
});
<h1 id="counter">00:00:00</h1>
The problem is that it seems to not go at the proper speed, meaning that when I compare it to other timers, it gradually becomes slower than them (i.e the speed at which the timer is counting slows down over time). So suddenly, there are 5-second differences, then it becomes 7-second differences and so on.
Any help would be appreciated.
You should create a startTime variable, then calculate the elapsedTime, and use that to calculate additional variable to show.
var startTime = Date.now();
setTimeout(function(){
var elapsedTime = Date.now() - startTime;
// Additional code to calculate hour, minute, second, milisecond here
}, 10);

my couter time gets reset on page load

recently i implemented a count timer for my shopping website that sets a limit of 24 hours when they create an order and not check out with a payment,so that counter reminds him/her that have to make a payment. The timer that is in our table is the start time and is adjusted by the current time up to 24 hours - after that, the order is cancelled.
Now i have a problem, when i reload the page the counter restarts from 24 hours this is my code
<script type="text/javascript">
function startTimer(duration, display) {
var start = '<?php echo $pending_order_date;?>';
function timer() {
// get the number of seconds that have elapsed since
// startTimer() was called
diff = duration - (((Date.now() - start) / 1000) | 0);
// does the same job as parseInt truncates the float
minutes = (diff / 60) | 0;
seconds = (diff % 60) | 0;
if(minutes >= 60){
hours = (minutes / 60) | 0;
minutes = (minutes % 60) | 0;
}else{
hours = 0;
}
hours = hours < 10 ? "0" + hours : hours;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = hours + ":" + minutes + ":" + seconds;
if (diff <= 0) {
// add one second so that the count down starts at the full duration
// example 05:00 not 04:59
start = Date.now() + 1000;
}
};
// we don't want to wait a full second before the timer starts
timer();
setInterval(timer, 1000);
}
window.onload = function () {
var twentyfourhour = 60 * 60 *24,
display = document.querySelector('#time');
startTimer(twentyfourhour, display);
};
</script>
Please see my code, i get the timestamp in php from my table and the count.
Your help would be appreciated.
You need to store your left off duration somewhere. localStorage seems to be better fit
function startTimer(duration, display) {
var start = '<?php echo $pending_order_date;?>';
function timer() {
// get the number of seconds that have elapsed since
// startTimer() was called
diff = duration - (((Date.now() - start) / 1000) | 0);
// does the same job as parseInt truncates the float
minutes = (diff / 60) | 0;
seconds = (diff % 60) | 0;
if(minutes >= 60){
hours = (minutes / 60) | 0;
minutes = (minutes % 60) | 0;
}else{
hours = 0;
}
hours = hours < 10 ? "0" + hours : hours;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = hours + ":" + minutes + ":" + seconds;
if (diff <= 0) {
// add one second so that the count down starts at the full duration
// example 05:00 not 04:59
start = Date.now() + 1000;
}
localStorage.setItem('timer', diff);
};
// we don't want to wait a full second before the timer starts
timer();
setInterval(timer, 1000);
}
window.onload = function () {
var twentyfourhour = 60 * 60 *24,
display = document.querySelector('#time');
var timePassed = localStorage.getItem('timer');
startTimer((typeof timer!=='undefined' ? timer : twentyfourhour), display);
};
so each time your duration changes, it will update localStorage timer value. when you reload page, it will look for timer item in localStorage and will get that value, if it doesn't exist then will use 24 hrs. you may also add a controller to remove timer once it is expired, and store it with the order number or something so you can use multiple values. but this should give you an idea.

How do you decrement time for minutes seconds hundredths?

Suppose you wanted to set a timer to whatever time you want will be displayed in the form 00:00:00 minutes, seconds, and hundredths. How would you go about doing so? Please any help is greatly appreciated.
Here is the link in JSFiddle:
https://jsfiddle.net/mxpuejvz/2/
function decrement(){
var time = 600;
var mins = parseInt((time / 100) / 60);
var secs = parseInt((time / 100) % 60);
var hundredths = parseInt(time % 100);
if(mins < 10) {
mins = "0" + mins;
}
if(secs < 10) {
secs = "0" + secs;
}
if(hundredths < 10) {
hundredths = "0" + hundredths;
}
document.getElementById("output").innerHTML = mins + ":" + secs + ":" + hundredths;
if (hundredths === 0){
if(time ===0){
clearInterval(countdownTimer);
document.getElementById("output").innerHTML = "Time's Up.";
}else{
time--;
}
var countdownTimer = setInterval('decrement()', 10)
}
}
}
Three issues appear to need attention.
"time to go" needs to be stored outside the screen update function and decremented or calculated each time the screen is updated.
using parseInt to convert numbers to integer numbers is regarded as a hack by some. Math.floor() or integer calculation can be alternatives.
Timer call backs are not guaranteed to made exactly on time: counting the number of call backs for a 10msec time does not give the number of 1/100ths of elapsed time.
The following code is an example of how it could work, minus any pause button action.
var countdownTimer;
var endTime;
var counter = 0; // ** see reply item 3. **
function startCountDown( csecs) // hundredths of a second
{ endTime = Date.now() + 10*csecs; // endTime in millisecs
decrement();
countdownTimer = setInterval(decrement, 10);
counter = 0; // testing
}
function decrement()
{ var now, time, mins, secs, csecs, timeStr;
++ counter; // testing
now = Date.now();
if( now >= endTime)
{ time = 0;
timeStr = "Times up! counter = " + counter;
clearInterval( countdownTimer);
}
else
{ time = Math.floor( (endTime - now)/10); // unit = 1/100 sec
csecs = time%100;
time = (time-csecs)/100; // unit = 1 sec
secs = time % 60;
mins = (time-secs)/60; // unit = 60 secs
timeStr =
( (mins < 10) ? "0" + mins : mins) + ":" +
( (secs < 10) ? "0" + secs : secs) + ":" +
( (csecs < 10) ? "0" + csecs : csecs);
}
document.getElementById("output").innerHTML=timeStr;
}
The argument to startCountDown gives the number of 1/100ths of second for the count down. If the counter result is the same as the argument,try swapping browser tabs and back again during the countdown.
HTML to test:
<button type="button" onclick="startCountDown(600)">start</button>
<div id="output">
</div>

Categories

Resources