I have been trying to create an attendance system that prompts a user for check-in and check out. Based on the input given, I have assigned a value time which increments by 1 after 1000 milliseconds(You can check in the code). But it is not working the way it has to. If I give check in and after one hour it doesn't show 1 hour. It is a bit slow than the actual time taken. I am not sure where the fault is. Please help me. For clarifications, I have concatenated the time and time taken after each second which you can see in the page itself. Thanks in advance!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
body {
background: black;
color: #fcbe24;
padding: 0 24px;
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 18px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
button {
font-size: 25px;
}
</style>
<body>
<h1 id="header"></h1>
<div>
<button id="start" style="display:block;" onclick="startTimer()">Check-in</button>
<button id="stop" style="display:none;" onclick="stopTimer()">Check-out</button>
</div>
<div id="time"></div>
</body>
<script>
var time = 0;
var startInterval;
function startTimer() {
if (time == 0) document.getElementById("time").innerHTML = "00:00:00";
startInterval = setInterval(startTime, 1000);
document.getElementById('start').style.display = 'none';
document.getElementById('stop').style.display = 'block';
}
function stopTimer() {
clearInterval(startInterval);
document.getElementById('start').style.display = 'block';
document.getElementById('stop').style.display = 'none';
}
function startTime() {
time++;
var seconds = time % 60;
var minutes = Math.floor(time / 60) % 60;
var hours = Math.floor(Math.floor(time / 60) / 60) % 24;
console.log(seconds, minutes, hours);
if (seconds < 10) seconds = "0" + seconds.toString();
else seconds = seconds.toString();
if (minutes < 10) minutes = "0" + minutes.toString();
else minutes = minutes.toString();
if (hours < 10) hours = "0" + hours.toString();
else hours = hours.toString();
var currentdate = new Date();
var datetime = currentdate.getHours() + ":" +
currentdate.getMinutes() + ":" +
currentdate.getSeconds();
document.getElementById("time").innerHTML += "<br>" + datetime + ", " + hours + ":" + minutes + ":" + seconds;
}
</script>
</html>
The current mainstream operating systems are not real-time OSes. They cannot guarantee that, if a program asks them to be notified after X milliseconds, it will be notified after exactly X milliseconds. They guarantee only that the program will be notified and that will not happen before X milliseconds pass.
The programs usually rely on timers provided by the operating system to do their time-related work.
Even if they do not do that, because the multitasking means that a program does not run continuously but it is interrupted by the OS, put to sleep then resumed later, the programs cannot guarantee that a time interval of X milliseconds will take exactly X milliseconds either. More than than, in order to be as close as possible, the programs must rely on the OS timers to be waked up when the time comes.
All in all, no program (on the mainstream operating systems) can guarantee that a time interval of X milliseconds will take exactly X milliseconds; you can rely, however, on the fact that it won't take less than X milliseconds.
In order to achieve your goal regarding time measurement (whatever that goal is), you need to carefully measure the time like this:
Get the current time and store it.
Set a timeout or an interval, as you need.
When the timeout passes and your callback is called, get the current time again.
If the difference between the two times is different than the length of your timeout or interval then adjust the length of the next timeout to compensate, if your processing needs that. Or just remember the difference and adjust it later. This depends entirely on your goal and on the way you implement it (timeout or interval).
If I give check in and after one hour it doesn't show 1 hour.
Adjust/correct it periodically, every time your callback is invoked and it will show 1 hour.
Related
I created a little script in Javascript, which is supposed to show to all the clients connected on the page some informations, actually an image every 90 seconds. This function is working perfectly fine on my computer, but as soon as I have to reload the page, all the process restart.
I don't know if there is a way to make the server calling this function, like this
//This should be a "server" variable in which users should be able to add their own image :
var images = [
['Canyon', 'https://www.w3schools.com/css/img_fjords.jpg'],
['Car Jumping', 'http://www.gettyimages.fr/gi-resources/images/Embed/new/embed2.jpg'],
['Birds Flying', 'http://ekladata.com/qWGncUdJ7U5k2vvmc1au-ZLnjlc.jpg'],
];
function Display (imagesarray) {
var rnd = Math.floor((Math.random() * imagesarray.length - 1) + 1);
document.getElementById("image").src = imagesarray[rnd][1];
}
function Timer(countDownDate) {
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = countDownDate - now + 2;
// Time calculations for days, hours, minutes and seconds
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Output the result in an element with id="demo"
document.getElementById("countdown").innerHTML = ("0" + minutes).slice(-2) + ":" + ("0" + seconds).slice(-2);
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("countdown").innerHTML = "FINISHED !";
Display(images);
}
}, 1000);
}
//This will call the Timer() function to end it in 01:30, and launch it again 10 seconds after the end of the previous call.
var y = setInterval(Timer(new Date().getTime() + 10000), 500);
p {
text-align : center;
font-size : 48px;
margin : 0px;
}
#note {
text-align : center;
font-size : 12px;
margin : 0px;
}
#image {
display : block;
margin : auto;
width : 150px;
height : 150px;
}
<p id="note">Counting only 10 seconds for example</p>
<p id="countdown">00:10</p>
<img id="image" src="http://vignette4.wikia.nocookie.net/destinypedia/images/b/b9/Unknown_License.png/revision/latest?cb=20130810221651">
Does anyone know how this could be managed by the server, so everybody have the same timer and the same picture displayed at the same time ?
Thanks a lot for your help !
[EDIT 1] The backend language I am using is PHP on this project
Breaking news: Time passes the same way all around the world :-D.
So there is no real need of "persistent connection" or so, as long as the users have set-up the time correctly on their computer. You just need to use the same base date for every user. Timestamps are very good at this because there is no time-zone problem with them.
Also note that it might be a better idea not using setTimeout setInterval for measuring time, because setTimeout could be renamed as runAfterAtLeastThatTimeIfYouDontHaveBetterToDo(). In deed, putting a setIterval(()=>{},1000) does not guarantee it will run every 1s, and you might experience desynchronization if the user switch tabs while browsing. You'd better run the interval function more than every seconds -every 10ms for example- if you want it to be accurate.
Usualy, I use requestAnimationFrame for displaying timer.
code :
In this code, I use the same base date for every users (I didn't put any 10s chill-time because I am lazy, but you can see the idea) :
const startDate = 0; // Unix epoch
const interval = 90000; // 90 seconds
var now = Date.now();
var count = (now - startDate) / interval; // should have run {{count}} times since Unix epoch
var next = Math.ceil(count) * interval + startDate; // so the next time it should run is at timestamp {{next}}
function timer() => {
var now = Date.now();
distance = next - now;
if (now >= next) {
document.getElementById("image").src = "http://domain.tld/my-script.php?now=" + now; // the query string parameter is just to avoid browser caching the image
next += interval;
} else {
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60))
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
document.getElementById("countdown").innerHTML = ("0" + minutes).slice(-2) + ":" + ("0" + seconds).slice(-2);
}
}
var requestID = window.requestAnimationFame(timer);
// use window.cancelAnimationFrame(requestID) to cancel the timer
A note on the img.src part:
this is the only part where the server is mandatory, you must implement a script that will send the image based on time. I added a queryString ?now=timestamp to avoid browser caching the image, and not keeping it up to date, but the server should rely on it's own date/time to display the image, not the one sent by the user.
PS : Note that I don't have anything against persistent connection via websocket or so, but that sounds a bit overkill for just displaying a timer and an image on a regular basis. If you think all your user have set their computer's time correctly and that it's not a big deal if some are not synched, use this solution. Otherwise, go for websocket.
You need to keep a persistent connection with the server possibly through websockets OR you can easily just send a variable from the server which tells the clients in how many seconds the next appearance should start.
I'm new to JS and I'm stuck trying to figure out what's causing my countdown timer not to countdown. The user enters the time in 00:00:00 format minutes, seconds, and milliseconds. Afterwards, I convert that format to seconds to begin the process of counting down. I think the calculations is fine, but something is not causing it not to behave as it should be. I've tested and see that the code runs in terms of entering the time and showing up in the output. I see the countdown decrementing, for both seconds and milliseconds at the same time but it should go from 10:00:00 to 09:59:99.. 09:59:98... Basically seconds won't change until milliseconds reaches zero. so 09:59:00 will be 09:58:99... Please any help is greatly appreciated. I've been going at this and been stuck.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript">
var running = 0; //Glob variable for starting/pausing timer
function startPause(){
var time = document.getElementById("timeEntered").value; //Not sure if needed but I just have the time entered be converted to seconds.
var a = time.split(":");
var timeToSeconds = (+a[0]) * 60 + (+a[1]) * 60 + (+a[2]);
if(running == 0){ //If off, turn it on.
running = 1;
countDown();
document.getElementById("startPause").innerHTML = "Start/Stop";
}else{
running = 0;
document.getElementById("startPause").innerHTML = "Resume";
}
}
function countDown() {
var time = document.getElementById("timeEntered").value; //Take user input and convert 00:00:00 format to seconds.
var a = time.split(":");
if(!timeToSeconds)
var timeToSeconds = (+a[0]) * 60 + (+a[1]) * 60 + (+a[2]);
if(running == 1){ //When user clicks start it will calculate the minutes, seconds, and milliseconds.
var minutes = Math.floor(timeToSeconds / 60);
var seconds = timeToSeconds % 60;
var milli = timeToSeconds % 100;
if(minutes <= 9) { //Add leading zeroes to display countdown in 00:00:00 format.
minutes = "0" + minutes;
}
if(seconds <= 9) {
seconds = "0" + seconds;
}
if(milli <= 9) {
milli = "0" + milli;
}
timeToSeconds--; //Decrement the time entered.
console.log(timeToSeconds);
document.getElementById("output").innerHTML = minutes + ":" + seconds + ":" + milli //Display the time 00:00:00 format.
if(timeToSeconds !== -1){
setTimeout('countDown()',100);
}
if(timeToSeconds == 0){ //When time is 00:00:00 the message will show.
document.getElementById("output").innerHTML = "The time is over."
}
}
}
</script>
</head>
<body>
<h1>Countdown Timer</h1>
<div id="mainCont">
<input type="text" id="timeEntered">
<p>
<button id="startPause" onclick="startPause()">Start/Stop</button>
</p>
<div id="output">00:00:00</div>
</div>
</body>
</html>
There are a handful of problem here, so I will go over each one and show you the solution. The first problem is that the value of timeToSeconds is the same on each iteration. The reason for this is because you are getting the value from the same unchanging source, decrementing does nothing as the value is lost on the next function call. To fix this have your function take a parameter in which you pass the remaining seconds off after you modified it:
function countDown(timeToSeconds) {
...
timeToSeconds-=0.1; //Decrement the time entered.
if(timeToSeconds <= 0){ //When time is 00:00:00 the message will show.
document.getElementById("output").innerHTML = "The time is over."
return;
}
else if(timeToSeconds !== -1){
setTimeout(function(){countDown(timeToSeconds)},100);
}
Notice I only subtracted 0.1 because our setTimeout is called after 100 milliseconds (0.1 seconds). I've also switched around the checks, as before hand you would call the timer even if timeToSeconds was 0.
The next thing was you conversion to seconds was off, in your code here:
var timeToSeconds = (+a[0]) * 60 + (+a[1]) * 60 + (+a[2]);
Both minutes and seconds are calculated in the same way, a[1] is the seconds value and should not be multiplied. And a[2] is actually 10*milliseconds (1 seconds = 1000 milliseconds). That value should be divide by 100:
if(!timeToSeconds)
var timeToSeconds = (+a[0]) * 60 + (+a[1]) + (Math.floor(+a[2]/100));
The if-statement is a basic check if the value is true (being any number). In our case it can work as a "Does this value exist" check, since we are only dealing with positive numbers. And the following conversions should be:
var minutes = Math.floor(timeToSeconds / 60) % 60;
var seconds = Math.floor(timeToSeconds) % 60;
var milli = Math.floor(timeToSeconds*100) % 100;
For the most part, your values for minutes and seconds where correct. Although the reason why milli and seconds appeared the same was because you never converted milli to it's correct value, as such they will have the same value apart from the % applied.
Here is the final result
One last thing I would like to point out is that this timer will not be exact. As it takes some time between the computation and the setTimeout call. For a more accuracy value you will want to use Date.now() and find the different between the start time and the current timer. This question uses such a method to do so, which can be applied to the countdown timer in the same fashion.
I am trying to make an easy countdown but it does not work the way I think it should work. This is the first time I use setInterval in Javascript and would be very happy if someone could find my mistake.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
function timer () {
window.clearTimeout(clock)
var seconds = 10;
var clock = setInterval(function() {
if (seconds == 0) {
} else {
seconds = seconds-1;
document.getElementById('seconds').innerHTML = seconds;
};
},1000);
}
</script>
<button onclick="timer();">timer</button>
<p id="seconds">10</p>
</body>
</html>
I hoped the timer would start-over when you clicked the button, but there are 2 timers running at the same time.
There are several problems with your code you need to address:
You need to make the clock variable global. In your example, an empty new variable clock is created each time the timer() function is called.
You are using the clearTimeout() function instead of the clearInterval() function.
The setInterval() function may miss some ticks and your seconds counter will then be off. If you wish to avoid that, you should check the current time each time the interval function is called.
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
var clock;
function timer () {
clearInterval(clock);
var start = new Date().getTime();
clock = setInterval(function() {
var seconds = Math.round(10 - (new Date().getTime() - start) / 1000);
if (seconds > 0)
document.getElementById('seconds').innerHTML = seconds;
else
clearInterval(clock);
}, 1000);
}
</script>
<button onclick="timer();">timer</button>
<p id="seconds">10</p>
</body>
</html>
A breakdown of Math.round(10 - (new Date().getTime() - start) / 1000):
new Date().getTime() returns the current time in milliseconds since the epoch.
(... - start) / 1000 returns the number of seconds since the start of the timer.
10 - ... returns the number of remaining seconds.
Math.round(...) rounds the result to an integer.
Just using setTimeout simplifies things (you used setInterval, but clearTimeout to clear it), declare the necessary variables outside the timer function and add a reset argument to be able to reset the timer.
(function () {
var report = document.querySelector('#seconds');
var seconds = 10;
var timed = null;
document.querySelector('button')
.addEventListener('click', function(e) { timer(true) });
timer(true);
function timer (reset) {
seconds -= 1;
if(reset) {
clearTimeout(timed);
seconds = 10;
}
report.textContent = seconds;
if (seconds > 0 ) {
timed = setTimeout(timer, 1000);
}
}
}())
#seconds {
font: 48px/70px bold verdana, arial;
color: white;
width: 70px;
height: 70px;
background: green;
text-align: center;
border-radius: 50%;
}
<button>start/reset timer</button>
<p id="seconds"></p>
i'm trying to build a page that takes the current hour and minute from the javascript date module and then makes the background color unique based off of that info.
what needs to change to get the html liked with the javascript? (new to this if you cant tell).
HTML
<html>
<head>
<meta charset="UTF-8">
<title>New color for each minute of day</title>
</head>
<body id="body">
<script src="script.js"></script>
</body>
</html>
JAVASCRIPT
var body = document.getElementById("body");
var a = 0;
var b = 0;
var c = 0;
function currentTime() {
var today = new Date();
var hour = today.getHours();
var minute = today.getMinutes();
minute = formatTime(minute);
text.innerHTML = hour + ":" + minute;
return minute
}
function changeColor() {
for (minute =< 59; a + 1);
for (hour =< 24; b + 10);
}
function setScene() {
timeValue = currentTime();
}
window.addEventListener("load", initialScene, false);
document.body.style.backgroundColor= 'rgb(' + a + ',' + b + ',' + c + ')';
Omit the CSS (style tag) in the first example and just use plain JS.
document.getElementsByTagName("body")[0].style.background="rgb("+a+", "+b+", "+c+");";
should do it
That's the main problem. Also, in your changeColor function, you are not using the for loop correctly, although you've got the right idea.
for (minute=0;minute<=59;minute+=1) {
a=minute;
}
for (hour=0;hour=<24;hour+=10) {
b=hour;
}
for loops can be a confusing subject for newcomers to JS, but there are some great tutorials online. Do a Google Search and really take the time to learn what a for loop does sometime, it's a good thing to know.
PS I don't see where c is defined.
I think you ask for a changing background for every minute of the day. You need to define a recurring function that reads the time and changes the color. You have that as setScene.
Now you can call it every 60 seconds automatically by pasting the following somewhere inside initialScene:
setInterval(setScene, 60000);
I'm currently learning some Javascript, and I'd made a realtime clock (well actually I modded W3school's code but whatever...I already figured out how to make a clock in PHP so no sense repeating that...)
Butttt the realtime clock doesn't seem to sync up with different devices, and I'd like to know why.
W3schools explains the date object as a count of the milliseconds since 1970, so I can't see why it would be wrong....it looks to me like instead of doing that, it's just mirroring whatever the computer's clock is.
When I pull up the website on a smartphone, the clock is 30 seconds or so off.
Is there maybe some way to make the clock reflect server time instead of each user's computer?
Here is the code
var ampm = "AM"; //Default
var message="";
function startTime()
{
var today=new Date();
var h=today.getHours();
var m=today.getMinutes();
var s=today.getSeconds();
// add a zero in front of numbers<10
m=checkTime(m);
s=checkTime(s);
h=checkTime2(h);
document.getElementById('clocktxt').innerHTML=h+":"+m+":"+s+ " " +ampm + " " + message;
t=setTimeout('startTime()',500);
}
function checkTime(i)
{
if (i<10)
{
i="0" + i;
message = "How long you gonna sit there?";
}
return i;
}
function checkTime2(i)
{
if (i>12)
{
i=i-12;
ampm="PM";
}
return i;
}
window.onload=startTime;
Your code is executed on "client" device - your smartphone, PC whatsoever.
So you have a time set on this device. This 'Date' object actually doesn't know anything about the time on server. The time is determined by the underlying Operating system installed on the client machine.
Your question is not really related to some specific technology (like Java Script, for instance), but rather how to get time synchronized on server and client machine.
Its quite complicated actually.
You can take a step further and ask how you can synchronize time between devices that belong to different time-zones. How about different calculations that should take into consideration 'daylight saving' time period?
As the common answer for time synchronization between computers you can read about Network Time Protocol, NTP
If you have enabled PHP you could do the following:
var serverTimeString = '<?php print date("F d, Y H:i:s", time())?>';
var today = new Date(serverTimeString);
Well, this is how I did it: (Does not vary at all)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Clock</title>
</head>
<body>
<div id="MyClockDisplay" class="clock" onload="showTime()">
</div>
<script>
function showTime(){
var date = new Date();
var h = date.getHours(); // 0 - 23
var m = date.getMinutes(); // 0 - 59
var s = date.getSeconds(); // 0 - 59
var session = "PM";
if(h == 02){
h = 12;
}
if(h > 12){
session = "PM";
}
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
var time = h + ":" + m + ":" + s + " " + session;
document.getElementById("MyClockDisplay").innerText = time;
document.getElementById("MyClockDisplay").textContent = time;
setTimeout(showTime, 1000);
}
showTime();
</script>
<style>
body {
background: url('imagename.jpg');
color: white;
}
.clock {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
color: #e6967e;
font-size: 60px;
font-family: 'Josefin Sans', sans-serif;
letter-spacing: 7px;
-webkit-transition: 0.5s;
}
.clock:hover {
transform: translateY(-10px);
transition: 0.5s;
font-size: 80px;
color: whitesmoke;
}
</style>
</body>
</html>
It will although differ between countries, but set automatically
The following code will give you the number of seconds from 1970. [Unix timestamp / Epoch time]
Math.round( new Date().getTime() / 1000 )