How I will do that:
When seconds come 31 (example 11:57 31sec.) do somthing, every minute. Using Javasript.
Thanks in advance.
Read the current time, calculate the number of seconds until the next time the seconds is ':31' then use setTimeout with the appropriate delay. You could use something like this:
var atSeconds = 31;
var secondsLeft = atSeconds - new Date().getSeconds();
if (secondsLeft <= 0) secondsLeft += 60;
setTimeout(foo, secondsLeft * 1000);
Remember to call it again in the function foo so that it repeats.
Something like this will probably be as close as you can get.
function initializeInterval() {
while (new Date().getSeconds() < 30);
setInterval(doWork, 60000);
}
function doWork() {
}
Related
I made a timer that will reach zero.
and when it reaches zero make the timer run again.
the timer goes back to the starting number but doesnt run again.
also when i call it again the numbers just start to jump.
the code:
var timerPlace = document.getElementById('timer');
var timerP = document.getElementById('timerHard');
var stopTimer;
var toStop;
function timeMed() {
console.log('im in!')
var counter = 0;
var timeLeft = 5;
timerPlace.innerHTML = '00:45';
function timeIt() {
console.log('here')
counter++
timerPlace.innerHTML = convertSeconds(timeLeft - counter);
if (timerPlace.innerHTML == '00:00') {
clearInterval(stopTimer);
resetExercise();
timeMed();
}
}
function convertSeconds(s) {
var sec = s % 60;
var min = Math.floor((s % 3600) / 60);
return ('0' + min).slice(-2) + ':' + ('0' + sec).slice(-2);
}
if (!stopTimer) {
stopTimer = setInterval(timeIt, 1000);
}
}
You only call setInterval() when stopTimer is not set. But after the countdown completes, stopTimer is still set to the ID of the old interval timer, so you don't restart it. You should clear the variable when you call clearInterval().
if (timerPlace.innerHTML == '00:00') {
clearInterval(stopTimer);
stopTimer = null;
resetExercise();
timeMed();
}
Modern ES6 Approach and best practices.
I've decided to take the chance and refactor your code a little with Javascripts best practices in mind.
I've added comments which explain the code, and the engineering considerations.
The baseline for the timer is taken from the excellent answer here: https://stackoverflow.com/a/20618517/1194694
// Using destructuring on the paramters, so that the keys of our configuration object,
// will be available as separate parameters (avoiding something like options.duraitons and so on.
function startTimer({duration, onUpdate , infinite}) {
let timer = duration, minutes, seconds;
let interval = setInterval(function () {
minutes = parseInt(timer / 60);
seconds = parseInt(timer % 60);
// you can also add hours, days, weeks ewtc with similar logic
seconds = seconds < 10 ? `0${seconds}` : seconds;
minutes = minutes < 10 ? `0${minutes}` : minutes;
// calling your onUpdate function, passed from configuraiton with out data
onUpdate({minutes, seconds});
if (--timer < 0) {
// if infinite is true - reset the timer
if(infinite) {
timer = duration;
} else {
// Clearing the interval + additonal logic if you want
// I would also advocate implementing an onEnd function,
// So that you'll be able to decide what to do from configuraiton.
clearInterval(interval);
}
}
}, 1000);
}
const duration = 5;
const displayElement = document.querySelector("#timer");
startTimer({
duration,
onUpdate: ({minutes, seconds}) => {
// now you're not constraint to rendering it in an element,
// but can also Pass on the data, to let's say your analytics platform, or whatnot
displayElement.textContent = `${minutes}:${seconds}`;
},
infinite: true
});
<div id="timer">
</div>
Here's the scenario, I have a time that counts the time_taken by a user. What I want is to get the exact time_taken based from the timer. For example, a user take an exam, then after he/she take the exam, the time_taken will be submitted (e.g. 1hr 25mins 23secs). Please see my code below.
$(document).ready(function(){
var d;
setInterval(function(){
d = new Date();
dates = d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds();
$('#timeTaken').val(dates);
}, 1000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="timeTaken" value="">
Here is Fiddle for the solution
https://jsfiddle.net/djzsddz6/1/
Ans Solution is below:
$(document).ready(function(){
var seconds = 0, minutes = 0 , hours = 0;
setInterval(function(){
seconds++;
if(seconds == 60){
minutes++
seconds = 0;
}
if(minutes == 60){
hours++
minutes = 0;
}
console.log(hours, minutes, seconds);
$('#timeTaken').val(`${hours}:${minutes}:${seconds}`);
}, 1000);
});
I don't really see the point to use an input there, you can just display in a span and when the form gets submitted take the time elapsed and send it with other data. Anyways, this should work for you:
$(document).ready(function () {
var time_start = new Date();
setInterval(function () {
var time_end = new Date();
var time_diff = (time_end - time_start);
// hours
var hours = Math.floor(time_diff / 1000 / 60 / 60);
// minutes
time_diff = time_diff - hours * 1000 * 60 * 60;
var minutes = Math.floor(time_diff / 1000 / 60);
// seconds
time_diff = time_diff - minutes * 1000 * 60;
var seconds = Math.floor(time_diff / 1000);
renderTime(hours, minutes, seconds);
}, 1000);
});
function renderTime (hrs, min, sec) {
var str = convertTime(hrs) + ":" + convertTime(min) + ":" + convertTime(sec);
$("#timeTaken").val(str);
}
function convertTime (val) {
return val < 10 ? "0" + val : val;
}
What's going on here is we have the time_start which does not change and we have setInterval function that is triggered every second. There we create new Date object, and the subtract the static one from it, which returns the time difference in milliseconds. We do the weird Math.flooring and subtracting, so we can have hours, minutes and seconds as an integers (not floats). Then we use render function to display the time inside an desired element.
Why I think it's a better solution then the others are, is that if you want to handle the user's page refresh you just need to save one variable to cookie or something else and it will work regardless of the page refresh.
Handling the page refresh would look like (with cookie saved for 2 hrs):
function updateTimeCookie () {
var time_now = new Date()
var value = JSON.stringify(time_now);
var expires = time_now.setTime(time_now.getTime() + 7200);
$.cookie("timeStart", value, { expires: expires });
};
// to get Date object from cookie: new Date(JSON.parse($.cookie("timeStart")))
To use $.cookie() you must first include jQuery Cookie Plugin.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
Working fiddle without cookie: https://jsfiddle.net/qc3axmf4/1/
Working fiddle with cookie: https://jsfiddle.net/ta8bnzs0/2/
Rather than getting date at every second you can keep the counter in set interval which will updated at every second. At the time of submission you can perform division and modulus operation to get exact time taken
Example
$(document).ready(function(){
var timer =0;
setInterval(function(){
Timer +=1;
// Code for display in hr mm and ss
$('#timeTaken').val(dates);
}, 1000'
});
You can also convert second in time valueby using moment.js
Hope this helps you.
Happy coding
I've a problem when running this script for my JavaScript countdown (using this plugin). What it should do is take the starting time, the current time and the end time and display the remaining time.
If I set these values with normal numbers in epoch time everything works just fine, but my question is: How do I set the current time and the start to be the real current one so that the countdown will be dynamic?
I've found this line: Math.round(new Date().getTime()/1000.0);
But I don't know how to make it work, considering I'm running this script at the bottom of my HTML file, before the </html> tag.
This is the script:
<script>
$('.countdown').final_countdown({
start: '[amount Of Time]',
end: '[amount Of Time]',
now: '[amount Of Time]'
});
</script>
This is how I tried to solve it, but it's not working:
//get the current time in unix timestamp seconds
var seconds = Math.round(new Date().getTime()/1000.0);
var endTime = '1388461320';
$('.countdown').final_countdown({
start: '1362139200',
end: endTime,
now: seconds
});
It sounds like you would like to count down from the current time to some fixed point in the future.
The following example counts down and displays the time remaining from now (whenever now might be) to some random time stamp within the next minute.
function startTimer(futureTimeStamp, display) {
var diff;
(function timer() {
// how many seconds are between now and when the count down should end
diff = (futureTimeStamp - Date.now() / 1000) | 0;
if (diff >= 0) {
display(diff);
setTimeout(timer, 1000);
}
}());
}
// wait for the page to load.
window.onload = function() {
var element = document.querySelector('#time'),
now = Date.now() / 1000,
// some random time within the next minute
futureTimeStamp = Math.floor(now + (Math.random() * 60));
// format the display however you wish.
function display(diff) {
var minutes = (diff / 60) | 0,
seconds = (diff % 60) | 0;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
element.innerHTML = minutes + ":" + seconds;
}
startTimer(futureTimeStamp, display);
};
<span id="time"></span>
Also Math.round(new Date().getTime()/1000.0); will give you the number of seconds since the epoch, however it may be a little disingenuous to round the number. I think you would be better served by taking the floor:
var timestamp = Math.floor(Date.now() / 1000)); is probably a better option.
In addition I am not sure why you need the start time, current time and end time. In order to find the remaining number of second you just need to know when the timer should end and the current time.
I have set my setInterval to 10 seconds. And it all working fine in my game, it count down from 10 seconds and change scene when it hit 0.
The problem is that I really would need to show milliseconds to and I cant understand how I will add it to the counter... It shouldnt be hard at all but I really cant figure it out.
Here is the script:
timer = 10;
clearInterval(countdownInterval);
countdown = function(){
timer--;
if (timer ==0){
gotoAndPlay("Scene 1",2 );
}
}
countdownInterval = setInterval(countdown,1000);
You probably need a Date() object which will report time deltas in milliseconds. Using setTimout to increment a timer is likely to have a number of problems.
var startTime = +(new Date) + (10 * 1000);
var checkFinished = function() {
timeRemaining = startTime - (new Date);
if(timeRemaining <= 0) {
gotoAndPlay("Scene 1",2 );
} else {
setTimeout(checkFinished, 100)l
}
}
setTimeout(checkFinished, 0);
I am trying to update information from a weather service on my page. The info should be updated every hour on the hour. How exactly do I go about calling a function on the hour every hour?
I kind of had an idea but I'm not sure of how to actually refine it so it works...
What I had in mind was something like creating an if statement, such as: (pseudo code)
//get the mins of the current time
var mins = datetime.mins();
if(mins == "00"){
function();
}
You want to check out setInterval: https://developer.mozilla.org/en-US/docs/Web/API/Window.setInterval
It's a little hard to tell what you're trying to call with your code, but it would be something in the form of:
function callEveryHour() {
setInterval(yourFunction, 1000 * 60 * 60);
}
If you want it every hour, try something like:
var nextDate = new Date();
if (nextDate.getMinutes() === 0) { // You can check for seconds here too
callEveryHour()
} else {
nextDate.setHours(nextDate.getHours() + 1);
nextDate.setMinutes(0);
nextDate.setSeconds(0);// I wouldn't do milliseconds too ;)
var difference = nextDate - new Date();
setTimeout(callEveryHour, difference);
}
Now, this implementation checks the time once, sets the delay (or calls the function immediately), and then relies on setInterval to keep track after that. An alternative approach may be to poll the time every x many seconds/minutes, and fire it .getMinutes() == 0 instead (similar to the first part of the if-statement), which may sacrifice (marginal) performance for (marginal) accuracy. Depending on your exact needs, I would play around with both solutions.
Here is what should work (JSFiddle):
function tick() {
//get the mins of the current time
var mins = new Date().getMinutes();
if (mins == "00") {
alert('Do stuff');
}
console.log('Tick ' + mins);
}
setInterval(tick, 1000);
What you probably want is something like that:
var now = new Date();
var delay = 60 * 60 * 1000; // 1 hour in msec
var start = delay - (now.getMinutes() * 60 + now.getSeconds()) * 1000 + now.getMilliseconds();
setTimeout(function doSomething() {
// do the operation
// ... your code here...
// schedule the next tick
setTimeout(doSomething, delay);
}, start);
So basically the first time the user get the access, you need to know what is the delay in millisecond to the next "hour". So, if the user access to the page at 8:54 (with 56 seconds and 123 milliseconds), you have to schedule the first execution after around 3 minutes: after the first one is done, you can call it every "hour" (60 * 60 * 1000).
Repeat at specific minute past the hour
This counter is a little bit more versatile; it allows to perform a task repeatedly always at the same minute past the hour (e.g. 37 minutes past the hour), and this with up to millisecond precision.
The precision of this timer is derived from its recursion.
At every recursion, the millisecond time to the next minute gets recalculated. This prevents time lag over long periods.
The % sign refers to the modulo operator.
function minuteCount(minutesAfterHour) {
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
const seconds = now.getSeconds();
const milliseconds = now.getMilliseconds();
waitUntilNextMinute = setTimeout(minuteCount, 60000 - seconds * 1000 - milliseconds);
if(minutes % 60 === minutesAfterHour) {
doSomethingHourly();
}
}
minuteCount(37);
Finally, timers are best kept away from the main thread. They are best run from within a web worker, as explained here.
This works perfectly with unfocused tabs in desktop browsers.
However, dedicated web workers on Chrome for Android are put to sleep about 5 minutes after moving the main client to the background.
EDIT: Oops, I didn't see the " o' clock" things, so I edit my answer :
var last_execution = new Date().getTime();
function doSomething(force){
var current_time = new Date().getTime();
if (force || (current_time.getMinutes() == 0)
{
last_execution = current_time;
// something
// ...
}
setTimeout(doSomething(false), 1000);
}
// force the first time
doSomething(true);
// ... call your func now
let intervalId;
let timeoutId = setTimeout(() => {
// ... call your func on end of current hour
intervalId = setInterval(() => {
// ... call your func on end of each next hours
}, 3600000);
}, ((60 − moment().minutes()) × 60 × 1000) - (moment().second() * 1000));
Here is my pair of setIntervalWithDelay and clearIntervalWithDelay that one can use like this:
let descriptor = setIntervalWithDelay(callback, 60 * 60 * 1000, nextHourDelay)
And when you are done with it:
clearIntervalWithDelay(descriptor)
Here is my implementation of the functions:
const setIntervalWithDelay = (callback, interval, delay = 0) => {
let descriptor = {}
descriptor.timeoutId = setTimeout(() => {
if(!descriptor.timeoutId){
return
}
descriptor.timeoutId = null
callback()
descriptor.intervalId = setInterval(callback, interval)
}, delay)
return descriptor
}
export const clearIntervalWithDelay = (descriptor) => {
if(!isObject(descriptor) || (!descriptor.timeoutId && !descriptor.intervalId)){
console.warn("clearIntervalWithDelay: Incorrect descriptor. Please pass an object returned by setIntervalWithDelay. Skipping this call.")
return
}
if(descriptor.timeoutId){
clearTimeout(descriptor.timeoutId)
descriptor.timeoutId = null
console.log("clearIntervalWithDelay: stopped during delay.")
}
if(descriptor.intervalId){
clearInterval(descriptor.intervalId)
descriptor.intervalId = null
console.log("clearIntervalWithDelay: stopped during interval repeat.")
}
}
One example of using dayjs to get the delay for the next hour:
let nextHour = dayjs().second(0).millisecond(0).add(1, "hour")
let nextHourDelay = nextHour.diff(dayjs())