Real Time decreasing value in php - javascript

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.

Related

Countdown timer in nodejs

I am creating a website for students which will be used to assign exams and I am having difficulties with the timer. The one I am using is made on the frontend in javascript and whenever the page is refreshed the timer startsover. Tried to store the start and end date by converting to epoch and back to datetime but I cannot think of a way to get the timer to the frontend and start counting. The idea is to count 60 minutes and call the submit button as well as to show the countdown without the option to restart the counter.
This is how I store the start and end time in nodejs.
var myDate = new Date();
var startTimeEpoch = myDate.getTime()/1000.0;
var endTimeEpoch = startTimeEpoch + 5400 // Adding 90 minutes to the timer
var startTimeBackToDate = new Date(startTimeEpoch *1000)
var endTimeBackToDate = new Date(endTimeEpoch *1000)
This is the javascript timer I am using and I am wondering if I should use one in the first place.
function startTimer(duration, display) {
var start = Date.now(),
diff,
minutes,
seconds;
function timer() {
diff = duration - (((Date.now() - start) / 1000) | 0);
minutes = (diff / 60) | 0;
seconds = (diff % 60) | 0;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (diff <= 0) {
start = Date.now() + 1000;
}
}
timer();
setInterval(timer, 1000);
}
window.onload = function () {
var fiveMinutes = "<%= scenario.time %>" * 60,
display = document.querySelector('#time');
startTimer(fiveMinutes, display);
}
As a general response and with the additional information provided, i could propose a solution to make this work.
If your students all have a specific exam entity attached to them, when they register/start an exam, you could retrieve the start date of this exam(add a mongo createdAt Date field) and use it as the starting date.
If each exam has a time limit, then you could simply do the math to know how much time is left. Something that will look like this:
const getExamRemainingTime = (exam) => {
// assuming that start is a js date object
// and timeLimit is an number representing the duration hours of your exam
const { start, timeLimit } = exam;
let end = (start.getHours() + timeLimit);
end = end.setHours(end);
const remainingTime = (+end) - (+start)
if (remainingTime > 0) {
// duration not finished, exam still in progress
return new Date(remainingTime);
} else {
// exam finished
return 0;
}
}
Then in your frontend, if it's plain javascript, you need to refresh your timer component, use setInterval in last ressort because it's very heavy on performance and format the date you got the way you want to show it.
Ref: casting js Date object to timestamp - How do you get a timestamp in JavaScript?.
I don't think a timer that a student with Javascript knowledge can modify should be used for serious tests, but for anything more light-hearted it should be fine.
The best system I can think of for this would be to have the test length stored in the mongodb and when a signed-in user starts the test, have the current time logged for that user. That way, you can calculate time remaining using user.testStart + test.length - Date.now().

jQuery time count

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

fire a time after specific date and time in javascript

i want to fire an event on specific date and time in javascript. for example ,
if current date and time is 19-11-2015 10:00 AM , and i set a timer on 19-11-2015 10:30 AM then , it should fire after 30 minutes. here set timer date could be after two days also.
my current code is as follows.
setTimer :function(hr , min){
var d1 = new Date();
var d2 = new Date();
console.log("Time 1 "+d1.getTime());
d2.setMinutes(d1.getMinutes() + min);
d2.setHours(d1.getHours() + hr);
console.log("Time 2 "+d2.getTime());
setTimeout(function(){
alert("called");
},d2.getTime());
alert("Before " + d1.getDate() + " - "+d1.getMonth() + " - "+d1.getFullYear() + "<>"+d1.getHours()+ ":"+d1.getMinutes()
+ "\n" +
"After " + d2.getDate() + " - "+d2.getMonth() + " - "+d2.getFullYear() + "<>"+d2.getHours()+ ":"+d2.getMinutes() );
},
i called it using setTimer(0,1); to fire a timer after one minute but its not getting fired.
Find out the time remaining using Date function and then pass it on to setTimeout function.No need to keep on checking the time.
$(document).ready(function(){
var d = new Date("November 19, 2015 17:00:00");
var d1 = new Date();
var timelimit = (d.getTime() - d1.getTime());
if(timelimit > 0) {
setTimeout(function(){
console.log(12345);
},timelimit);
}
});
Using setTimeout is not a reliable way to create timers.
You're much better off using setInterval and checking whether you've reached the correct time yet.
function setTimer(hours, minutes) {
var now = Date.now();
// work out the event time in ms
var hoursInMs = hours * 60 * 60 * 1000,
minutesInMs = minutes * 60 * 1000;
var triggerTime = now + hoursInMs + minutesInMs;
var interval = setInterval(function() {
var now = Date.now();
if(now >= triggerTime) {
alert('timer!');
// clear the interval to avoid memory leaks
clearInterval(interval);
}
}, 0);
}
You'll save yourself a lot of bother if you use Date.now which returns the date as the number of milliseconds since the epoch. Then you can just treat the problem numerically, rather than messing with the date api.

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.

Javascript Countdown Timer - Client Time vs mySQL Time

The following code is a countdown timer. It pulls an ending datetime stamp from mySQL and uses it to count to. The issue is that the mysql time may be in a different time zone than the client who is looking at the page with the timer.
I also pull the current timestamp from mySQL with NOW(), thinking that this would allow the timer to count as the user who created it intended.
if I put the NOW() value in this snippet
var timeDiff = target - (new Date());
like so
var nt='2015-03-11 05:12:15'.split(/[- :]/);
var timeDiff = target - (new Date(nt[0],nt[1]-1,nt[2],nt[3],nt[4],nt[5]));
the counter shows the correct time left when the page loads but does not count interactively any longer. I think I need to get the difference in hours between the clients local time and the mySQL NOW() and adjust the date in this line to get the interactive timer to run.
var timeDiff = target - (new Date());
nothing I try seems to work.
This is the working script if the client happens to be int he same time zone.
<script language="javaScript">
document.write(hrs);
function timeDiff(target) {
function z(n) {return (n<10? '0' : '') + n;}
var timeDiff = target - (new Date());
var hours = timeDiff / 3.6e6 | 0;
var minutes = timeDiff % 3.6e6 / 6e4 | 0;
var seconds = timeDiff % 6e4 / 1e3 | 0;
if (hours<0 || minutes<0 || seconds<0) {
document.getElementById('divBody').style.display='none';
document.getElementById('divExpired').style.display='';
return '<b>EXPIRED</b>';
}
else {
return '<b>' + z(hours) + '</b> Hours, <b>' + z(minutes) + '</b> Mins, <b>' + z(seconds) + '</b> Secs';
}
}
function doCountDown(target) {
document.getElementById('timer').innerHTML = '<img src=\"/backhaul/images/my/al-active.png\" class=\"vm2\" /> <span style=\"color:#c40000\"><b>EXPIRES IN</b></span>: ' + timeDiff(target);
var lag = 1020 - (new Date() % 100);
setTimeout(function(){doCountDown(target);}, lag);
}
window.onload = function() {
//Insert Expiratin Date from mySQL into t var
var t='2015-03-12 00:00:00'.split(/[- :]/);
doCountDown(new Date(t[0],t[1]-1,t[2],t[3],t[4],t[5]));
}
</script>
There are many ways of doing this, but I'll elaborate on two ways.
Method 1 : Adjust the time on the client side
One way is what you are trying to do which is to get the current time of the server and find the difference with the client's current time. You can simply adjust the server target time to the client's time. This can be done with
var serverDifference=Date.parse(mysql_data.now)-Date.now()
var target=Date.parse(mysql_data.server_time_in_two_hours)-serverDifference
Then you can input it into your function without problem.
Method 2: Calculate the times remaining, server side
Since you just need a countdown timer, I think it's more appropriate to simply send the seconds left server side. This can be done with SQL using
select timestampdiff(SECOND,now(),end_time) seconds_left from timers;
Then you simply just make a timer that counts down based on the number of seconds left instead of a target date. You can calculate the number of seconds left by deducting the time that the javascript has run from the time received from the server. So something like
var client_start=Date.now()
function timeDiff_fromseconds(target) {
function z(n) {return (n<10? '0' : '') + n;}
var timeDiff =target-(Date.now()-client_start)
var hours = timeDiff / 3.6e6 | 0;
var minutes = timeDiff % 3.6e6 / 6e4 | 0;
var seconds = timeDiff % 6e4 / 1e3 | 0;
if (hours<0 || minutes<0 || seconds<0) {
return '<b>EXPIRED</b>';
}
else {
return '<b>' + z(hours) + '</b> Hours, <b>' + z(minutes) + '</b> Mins, <b>' + z(seconds) + '</b> Secs';
}
}
There is also performance.now() as suggested by #dandavis. This returns the number of milliseconds since the tab opened and is accurate to 1/1000th of a millisecond. And this doesn't change even if the system clock of the client browser changes. For full support, you should use a polyfill (As of the time of this writing, iOS Safari doesn't support it). In this context we can replace Date.now() with it.
JSFiddle Demo:
http://jsfiddle.net/3o3u5r5j/1/
If it is possible to get remaining amount of seconds from database instead of expiry time (meaning to calculate it at the server and send to the client). Then you can use following code (sample). Fiddle
var countDownId;
var timer;
function countDown(){
console.log(timer--);
if(timer<=0){
clearInterval(countDownId);
alert('time expired');
}
}
function startCountDown(secondsToExpire){
var milliseconds = 1 * 1000 ;// 1 second
timer = secondsToExpire;
countDownId = setInterval(function() { countDown();},milliseconds);
}
window.onload = function() {
//Insert remaining time from expiration
var timeRemaining = 5;
startCountDown(timeRemaining);
}
You can tweak this to suit your needs.

Categories