I'm writing a Greasemonkey script where I want to know when it was last run. To do this, I wanted to store the current time with GM_setValue and compare that time to the time when the script is run again.
However, it seems that the Date().getTime() results won't pass to GM_setValue. For instance if you run:
var newtime = new Date().getTime();
GM_setValue('lastrun', newtime);
alert(GM_getValue('lastrun'));
There's obviously errors since the alert box won't pop up. However if you replace the first line with:
var newtime = 1;
you then get 1 returned in the alert box like you would expect.
That pretty much just isolates the date format causing the issue here. Any ideas on how to deal with this, or better ways to save dates between times a script has run?
I had a similar issue. The number is too large to be stored as a firefox cookie value. My solution was to limit the precision to the second (divide by 1000, drop remainder) and subtract 43 years (1356998400 seconds) to bring the date measured from to Midnight Jan 1st 2013 so my code looks like this:
var time = Math.floor((new Date().getTime() / 1000) - 1356998400);
GM_setValue("runTime", time);
and the retrieval looked like:
var time = GM_getValue("runTime", 0);
if (time != 0) {
var cur = Math.floor((new Date().getTime() / 1000) - 1356998400);
var cur = cur - time;
var sec = cur % 60;
var min = Math.floor(cur / 60);
console.log("Script took " + min + ":" + sec);
}
Related
I am trying to make a JavaScript countdown timer to UTC midnight that works in a browser (which typically converts to local time).
It seems to work most of the time, but for some reason it will go negative sometimes. I want it to always display time until midnight UTC.
-3 hours 23 minutes 34 seconds
I'm pretty sure I tested this on crossing midnight, but lately it's been going negative like it isn't pulling a new date.
Here is what I am using now on my website.
setInterval(() => {
let toDate = new Date()
let tomorrow = new Date()
tomorrow.setHours(24, 0, 0, 0)
let diffMS =
tomorrow.getTime() / 1000 -
toDate.getTime() / 1000 -
toDate.getTimezoneOffset() * 60
let diffHr = Math.floor(diffMS / 3600)
diffMS = diffMS - diffHr * 3600
let diffMi = Math.floor(diffMS / 60)
diffMS = diffMS - diffMi * 60
let diffS = Math.floor(diffMS)
let result = diffHr + ' hours '
result += diffMi + ' minutes '
result += diffS + ' seconds '
this.timeRemaining = result
}, 1000)
Not sure exactly where your issue is from, but using local time adjusted by offset is somewhat fraught. Also the offset changes over a DST boundary so that might be an issue too (or not) so the countdown will jump the equivalent of the change in offset (either + or -).
It's very much simpler to set the end using UTC methods and count down to that, e.g.
// Return time to next UTC midnight as x hours x minutes x seconds
function toMidnightUTC(date = new Date()) {
let d = new Date(+date);
d.setUTCHours(24,0,0,0);
let diff = d - date;
return `${diff/3.6e6 |0} hours ` +
`${diff%3.6e6 / 6e4 |0} minutes ` +
`${diff%6e4 / 1000 |0} seconds`;
}
// Run 20ms after next full second
let runIt = ()=> {
document.getElementById('s0').textContent = toMidnightUTC();
let lag = 1020 - new Date() % 6e4;
setTimeout(runIt, lag);
};
// Start the process…
runIt();
<span id="s0"></span>
Note that setInterval isn't a good way to do a countdown as the interval is not guaranteed to run every second and typically slowly drifts so it doesn't tick with the system clock and drifts, so skips a second from time to time.
Better to use setTimeout and get the time to the next full second each time so it runs very close to the system clock tick and rarely skips (though it still might if the system is working hard).
Ok on My dev machine I have the following code:
JScript
setInterval(function () { myTimer(); }, 1000);
function myTimer() {
var d = new Date();
var hrs = d.getHours();
var min = d.getMinutes();
var sec = d.getSeconds();
var dayOfWeek = d.getDay();
// Let's do this logically.
// To get the number of victims so far today we need to know how many seconds have passed so far today.
var totalSeconds = sec + (min * 60) + (hrs * 3600); // Number of Seconds passed so far today.
// Now multiply that by 14 in accordance with Symantec's research.
var VictimsToday = totalSeconds * 14;
// To get the number of victims this week we need to multiply
// The number of seconds in a day by the number of full days and add the number of seconds of this partial day.
var TotalSecondsInADay = 86400; // According to Google.
var DaysSoFarThisWeek = dayOfWeek + 1; // Removes today as a partial day.
// We already know how many seconds are in this partial day = totalSeconds
// So our calculation is
var tsD = TotalSecondsInADay * DaysSoFarThisWeek;
var VictimsThisWeek = (totalSeconds + tsD) * 14;
// Now we get the Day of the Year remove today as a partial day and calculate
// Number of seconds a day by the number of complete days so far + todays partial day
var DOY = DayOfYear();
var tsY = DOY * totalSeconds;
var VictimsThisYear = (totalSeconds + tsY) * 14;
document.getElementById("FooterStatistics").innerHTML = Intl.NumberFormat().format(VictimsToday);
document.getElementById("FooterStatistics2").innerHTML = Intl.NumberFormat().format(VictimsThisWeek);
document.getElementById("FooterStatistics4").innerHTML = Intl.NumberFormat().format(VictimsThisYear);
}
function DayOfYear() {
var today = new Date();
var first = new Date(today.getFullYear(), 0, 1);
var theDay = Math.round(((today - first) / 1000 / 60 / 60 / 24) + 0.5, 0);
return theDay;
}
With the HTML being:
BODY
<div id="FooterStatistics"></div>
<div id="FooterStatistics2"></div>
<div id="FooterStatistics4"></div>
Now on the Dev machine the calculation returned in the DIV is:
However, when I run this on W3Schools Tryit Editor: http://www.w3schools.com/js/tryit.asp?filename=tryjs_date_getday
I get a totally different calculated result:
Now I know the numbers will be different because of TimeZone differences - what should not be different is the actual calculations. The Dev machine's second result is smaller than the first which it should NEVER be, and the third result is apparently not even a number - where upon the results in the TryIt editor provide more reasonable asnwers.
How can this be?
While creating apps, keep using console.log() to check the values. This really helps to understand what is happening, in the future. This is not an alternative to debugging, though, but it helps. You could only remove them when your code is to go live, or you are sure it works and is well abstracted.
PS: Avoid using w3schools.com. Use MDN. It's much better.
I want to implement a count-up timer JS code that starts counting at each load page from 0. The code which I've now is like this:
var secondsTotal = 0;
setInterval(function() {
++secondsTotal;
var minutes = Math.floor(secondsTotal / 60);
var seconds = Math.floor(secondsTotal) % 60;
var milliseconds = Math.floor(secondsTotal) % 1000;
document.getElementById('counter').innerHTML = minutes + ":" + seconds + "." + milliseconds;
}, 1000);
The output format should be: 00:00.0
mm:ss.ms
So, how to output the result like above format (minutes and seconds should be exactly printed in two digits format)?
If you want to do it per-page, you're almost there. Right now, your code does not allow you to track milliseconds, as your setInterval runs every second. What I would recommend instead is something like this:
(function() {
var counter = 0,
cDisplay = document.getElementById("counter");
format = function(t) {
var minutes = Math.floor(t/600),
seconds = Math.floor( (t/10) % 60);
minutes = (minutes < 10) ? "0" + minutes.toString() : minutes.toString();
seconds = (seconds < 10) ? "0" + seconds.toString() : seconds.toString();
cDisplay.innerHTML = minutes + ":" + seconds + "." + Math.floor(t % 10);
};
setInterval(function() {
counter++;
format(counter);
},100);
})();
This does a couple of things to allow your code to run 10 times per second:
The output element, #counter, is cached and not retrieved every iteration
The formatting is kept to arithmetic operations only - modulo and division.
This now also adds leading zeroes.
If you would like to keep this counter running page-per-page, consider using document.cookies to pass the final value from page to page.
Fiddle
This serves as a good first version. However, you may want to:
Pause/re-start your timer
Reset your timer
Have multiple timers
For this reason, I will add a slightly more complex form of the above code, which will allow you to manage multiple timers. This will make use of a few OO concepts. We will use a TimerManager object to "host" our timers, and each Timer object will have a link to the manager.
The reason for this is because every timer will depend on the same setInterval() by doing it this way, rather than to have multiple setInterval() calls. This allows you to cut down on wasted clock cycles.
More on this in about 5 minutes!
Counting seconds that way isn't guaranteed to be accurate. The setInterval method can drift on you based upon the JS engine's ability to complete its other tasks. Not sure what your use case is, such as how long you expect to count up, but it's worth taking note of. See Will setInterval drift? for a detailed explanation.
I'd recommend you check out the momentjs plugin # http://momentjs.com/ and update your code to something like the following
var startTime = moment();
var el = document.getElementById('counter');
setInterval(function() {
var ms = moment().diff(startTime),
min = moment.duration(ms).minutes(),
sec = moment.duration(ms).seconds();
ms = moment.duration(ms).milliseconds();
min = (min < 10) ? "0" + min.toString() : min.toString();
sec = (sec < 10) ? "0" + sec.toString() : sec.toString();
ms = ms.toString().substring(0,2); // change this if you want to expand ms counter display
el.innerHtml = min + ":" + sec + "." + ms;
}, 50);
You're free to update the interval, and your milliseconds display without adjusting your calculations.
I trying to create a very simple time difference calculation. Just "endtime - starttime". I'm getting +1 hour though. I suspect it has with my timezone to do, since I'm GMT+1.
Regardless, that should not affect the difference, since both start and end times are in the same timezone.
Check my running example-code here:
http://jsfiddle.net/kaze72/Rm3f3/
$(document).ready(function() {
var tid1 = (new Date).getTime();
$("#tid").click(function() {
var nu = (new Date).getTime();
var diff = new Date(nu - tid1);
console.log(diff.getUTCHours() + ":" +
diff.getUTCMinutes() + ":" +
diff.getUTCSeconds());
console.log(diff.toLocaleTimeString());
});
})
You must understand what Date object represent and how it stores dates. Basically each Date is a thin wrapper around the number of milliseconds since 1970 (so called epoch time). By subtracting one date from another you don't get a date: you just get the number of milliseconds between the two.
That being said this line doesn't have much sense:
var diff = new Date(nu - tid1);
What you really need is:
var diffMillis = nu - tid1;
...and then simply extract seconds, minutes, etc.:
var seconds = Math.floor(diffMillis / 1000);
var secondsPart = seconds % 60;
var minutes = Math.floor(seconds / 60);
var minutesPart = minutes % 60;
var hoursPart = Math.floor(minutes / 60);
//...
console.log(hoursPart + ":" + minutesPart + ":" + secondsPart);
Working fiddle.
I'm trying to do a program which executes after 15 minutes of being in the page. My problem is how to get the exact number to add on the timestamp which is stored in a cookie.
I need a function to convert seconds into timestamps or anything that can make the action execute after 15 minutes. I don't really know how much time is 1792939 which I place in the code below.
setInterval("timer()",1000);
$.cookie("tymz", time);
function timer(){
var d = new Date();
var time = d.getTime();
var x = Number($.cookie("tymz")) + 1792939;
//alert('Cookie time: ' + x + '\nTime: ' + time);
if(time > x){
alert('times up');
}else{
//alert('not yet\n' + 'times up: ' + x + '\ntime: ' + time);
}
}
How about using setTimeout(..)?
<script type="text/javascript">
function myFunc()
{
alert("I will show up 15 minutes after this pages loads!");
}
setTimeout("myFunc()",60*15*1000);
</script>
Check this: http://www.w3schools.com/js/js_timing.asp
unix timestamp are second from epoch (1/1/1970) so if you want to execute some code after 15 minutes just record the time when the page is loaded then every second calculate how many seconds are passed from page load. When the difference between current time and page load time is greater than 15*60*1000 you can execute your code.
var pageLoad = new Date().getTime();
function tick(){
var now = new Date().getTime();
if((now - pageLoad) > 15*60*1000) executeYourCode();
}
setInterval("tick()",1000);
Remeber that javascript return time in millisecond
Hope this helps
If the number is seconds since 1/1/1970 00:00:00, then you can convert '1792939' to a javascript date by multiplying by 1,000 and passing to Date:
var d = new Date(1792939 * 1000) // Thu Jan 22 1970 04:02:19
Currently it is about 1311428869 seconds since 1/1/1970. So if you have a value for seconds, then you can use setInterval to run a function 15 minutes after that:
var seconds = ?? // set somehow
var start = new Date(seconds * 1000);
var now = new Date();
var limit = 15 * 60 * 1000;
var lag = now - start + limit;
// Only set timeout if start was less than 15 minutes ago
if ( lag > 0 ) {
setTimeout( someFn, lag);
}
Provided the current time is less than 15 minutes from the start time, the function will run at approximately 15 minutes after the start time. If the system is busy when the time expires, the function should be run as soon as possible afterward (usually within a few ms, but maybe more).
works without server or cookie (and all browser after IE7)
Looks like you use jQuery, so you might as well use jQuery.now() insted
var firstVisit = localStorage['firstVisit'] = localStorage['firstVisit'] || $.now();
function myFunc(){
alert("I will show up 15 minutes after this pages loads!");
}
setTimeout(myFunc, parseInt(firstVisit) - $.now() + 1000 * 60 * 15);