I was having some problem when trying to perform some calculation logic using JavaScript. Basically along a route there is 80 steps and it took around 9 minutes to finish up the entire route.
So I was trying to do an auto route which will tell you the minutes left to destination. My logic is as below:
9 * 60 / 80 = 6.75
So basically for each step is 6.75 seconds but I wanted to show a round number like 9 instead of 8.4 minutes. Here is the code:
getAllBusLoc(function(busList) {
var totalBusLoc = busList.length;
var busLeftPct = Math.round(parseFloat(busList.length) * 40 / 100)
document.getElementById("busStopLeft").innerHTML = totalBusLoc;
pointArr.forEach(function(coord,index){
setTimeout(function(){
var travelTime = document.getElementById(travelDistMin").value;
moveNext(coord.x, coord.y);
}, 1000* index);
});
});
I got the travel time as variable travelTime which in this case is 9 minutes. For each point, I wanted to minus 6.75 seconds from the 9 minutes and display a round number instead of 8.2.
Any ideas?
Thanks in advance.
Use Math.round() for subtracting 6.75 from travelTime.
This is will round to the nearest whole number.
An idea that I could suggest is to write a generic function that transforms a decimal time interval (for example, 8.25 minutes) into its equivalent 'mm:ss' value instead of rounding so that you display the precise time representation:
Number.prototype.toMMSS = function () {
d = this;
var sign = d < 0 ? "-" : "";
var min = Math.floor(Math.abs(d))
var sec = Math.floor((Math.abs(d) * 60) % 60);
return sign + (min < 10 ? "0" : "") + min + ":" + (sec < 10 ? "0" : "") + sec;
};
Example:
8.25.toMMSS() // "08:15"
JSFiddle
Or, you could try the moment plugin duration function like:
moment.duration(8.25, 'minutes').minutes(); // 8
Or, the humanize method to round off:
console.log(moment.duration(8.51, "minutes").humanize()); // "9 minutes"
console.log(moment.duration(8.15, "minutes").humanize()); // "8 minutes"
Related
I'm trying to create a countdown to get the remaining time before my shop will close
// My array for the opening hours :
var openTime = [
{ open : 9, close : 17},
{ open: 9, close : 18 },
{ open: 9, close : 18 },
{ open: 9, close : 18 },
{ open: 9, close : 18 },
{ open: 9, close : 18 },
{ open: 10, close : 16.5 }
]
var current = new Date();
var day = current.getDay();
var currentTime = current.getHours() + (current.getMinutes() / 60);
var remainTime = 0;
if (openTime[day].open >= 0 && openTime[day].open < currentTime && openTime[day].close >
currentTime) {
remainTime = (openTime[day].close - currentTime).toFixed(2)
}
console.log("the shop will close in %s hours", remainTime);
But I have a problem with this line :
var currentTime = current.getHours() + (current.getMinutes()/60);
Because when I execute the code, for exemple, actually it's 17h22, the code give me on my debugger that current time equal to 17.36 ?
There is something wrong with the line, because it's give me the wrong remaining time...
0.36 of an hour (a decimal magnitude) equals 21.6 (≈22) minutes.
It's simple to convert decimal to minutes: 60*decimal. Or (60*decimal).toFixed(0) or (60*decimal).round() if you want a round number.
Also, remember that JS uses the device's time. Today most devices sync their time, but if you don't want to rely on it, you should bring the time from your server (ie. storing it in a JS variable at preprocessing time, like var time=<?=time()?>;).
If you want current time as string you have to:
var currentTime = current.getHours() + ":" + (current.getMinutes() / 60);
but thats not what you want I guess. You get of coures 17.36 because 17:22 converted to decimal base 10 instead of 60 minutes gives this value (22 min /60 =0.363636 rounded two digits 0.36). If you want to have the timer working you convert either back the decimal part by *60 to easy find it. Use:
var decimalPart = remainTime % 1;
var remainTimeHours = remainTime - decimalPart;
var remainTimeMin = decimalPart * 60;
Of course you can simplify it - just to show the logic
-in your closing time you use already 16.5 means 16:30 or should it be 16:50 -> then 16.83
or preferred seperate logic for hours and minutes not converted to decimal using even seconds if needed.
I am having trouble making a stopwatch that only uses 2 digits for the milliseconds part. I have the full JSFiddle here. The function I could use some help with is the formatter() method.
Right now, the method looks like this:
formatter(timeInMilliseconds) {
const padZero = (time) => {
while (time.length < 2) {
time = '0' + time;
}
return time;
}
let time = new Date(timeInMilliseconds);
let minutes = padZero(time.getMinutes().toString());
let seconds = padZero(time.getSeconds().toString());
let milliseconds = padZero((time.getMilliseconds() / 10).toFixed(0));
let output = `${minutes} : ${seconds} . ${milliseconds}`;
console.log(output);
return output;
}
For the most part, it works. The problem though is very visible if you look at the console of my JSFiddle while the timer is running. For example, if the stopwatch is currently at something like 00 : 15 . 99, it will become 00 : 15 . 100 at the next tick instead of 00 : 16 . 00.
Any help would be appreciated.
toFixed rounds rather than truncating, so 995 milliseconds and up will become 99.5 and be formatted to 100 by toFixed. You can convert it to an integer and then to a string instead to truncate it:
let milliseconds = padZero('' + (time.getMilliseconds() / 10 | 0));
It might also be a nice simplification to make padZero accept a number rather than a string:
function padZero(time) {
return time < 10 ? '0' + time : '' + time;
}
let time = new Date(timeInMilliseconds);
let minutes = padZero(time.getMinutes());
let seconds = padZero(time.getSeconds());
let milliseconds = padZero(time.getMilliseconds() / 10 | 0);
let output = `${minutes} : ${seconds} . ${milliseconds}`;
Finally, if timeInMilliseconds isn’t a timestamp in milliseconds since 1970-01-01 00:00:00 UTC and is instead a duration, it’s inappropriate to convert it to a Date. Just do some math:
const minutes = padZero(timeInMilliseconds / 60000 | 0);
const seconds = padZero((timeInMilliseconds / 1000 | 0) % 60);
const centiseconds = padZero((timeInMilliseconds / 10 | 0) % 100);
Your problem is that .toFixed() rounds instead of truncating.
(99.4).toFixed(0) == '99'
(99.5).toFixed(0) == '100'
All you need to do is replace
(time.getMilliseconds() / 10).toFixed(0)
with
Math.floor(time.getMilliseconds() / 10).toFixed(0)
and it'll work.
You can use substring()
let milliseconds = padZero((time.getMilliseconds() / 10).toFixed(0)).substr(0, 2);
This appears in the middle of a function, I wrote it myself and im stuck.
What it does it make a call for the time in milliseconds, (countStart) and then it makes a call for the time when it completes (countEnd). When this is activated, it looks at the countStart countEnd and does the math to determine if it has run long enough to run again.
All of this is successful, except, it displays everything in seconds, so 3 minutes is 180 seconds. I am trying to figure a way to make it count down 3 minutes correctly.
Is this a feasible thing? I have done hours of research and I can find 50 ways to supposedly do this, and all of them are HTML based and massively large. I tried to add a if this goes above 60 function then add 1 to minutes and subtract 60 from seconds, but that locked up the counter.
So anyway any help or guidance would be appreciated
var countStart = 100000000000000;
var countStop = 100000000000020;
var countDelay = 180000;
alert(parseInt((factor * -1) / 1000, 10) + " s)");
for (var factor = countStop - (countStart + countDelay) + 1; factor > 0; factor--){
countStart = 0;
countStop = 0;
countDelay = 0;
}
Do the math:
var time_in_seconds = ...;
var minutes = (time_in_seconds / 60) | 0; // divide by 60 and truncate to an integer.
var seconds = time_in_seconds % 60; // this is the modulo operator
If you don't like the modulo operator for no obvious reason, then you can do further math:
var minutes = (time_in_seconds / 60) | 0;
var seconds = time_in_seconds - minutes * 60;
To format the two integers:
var string = minutes + "m" + (seconds < 10 ? "0" + seconds : seconds);
condition ? then_expr : else_expr is the ternary operator. If the condition is true, then then_expr gets evaluated, otherwise else_expr.
In my system, time stamps are returned using the old IBM julian format.
For example:
12 o'clock 0 minutes and 1 seconds AM (1 sec after midnight) is returned 01.
12 o'clock 22 minutes and 15 seconds AM is returned 2215.
1 o'clock 22 minutes and 15 seconds AM is returned 12215.
7 o'clock 45 minutes and 1 seconds AM is returned 74501.
7 o'clock 22 minutes and 15 seconds PM is returned 192215.
I need a regex expression to put these into the format of:
12 o'clock 0 minutes and 1 seconds AM (1 sec after midnight): 00:00.01
12 o'clock 22 minutes and 15 seconds AM: 00:22.15
1 o'clock 22 minutes and 15 seconds AM: 01:22.15
7 o'clock 45 minutes and 1 seconds AM: 7:45.01
7 o'clock 22 minutes and 15 seconds PM: 19:22.15
Any help is appreciated.
SOLUTION
Thanks to MikeM, here is the solution:
//var time = '01';
//var time = '2215';
//var time = '12215';
//var time = '74501';
var time = '192215';
time = time.replace( /^(?:(?:(\d)?(\d))?(\d\d))?(\d\d)$/,
function ( all, hr1, hr2, min, sec ) {
return (hr1 || '0') + (hr2 || '0') + ':' + (min || '00') + '.' + sec;
}
);
The following works with your examples, though I haven't tested it beyond that
//var time = '01';
//var time = '2215';
//var time = '12215';
//var time = '74501';
var time = '192215';
time = time.replace( /^(?:(?:(\d)?(\d))?(\d\d))?(\d\d)$/,
function ( all, hr1, hr2, min, sec ) {
return (hr1 || '0') + (hr2 || '0') + ':' + (min || '00') + '.' + sec;
}
);
Although it gives 07:45.01 not 7:45.01, so as to be in keeping with 01:22.15.
I'll give you a clue:
Convert returned value to a number.
num % 100 is the seconds.
(num / 100) % 100 is the minutes.
(num / 10000) is the hours.
If the hours is less than 12, use AM
If the hours is 12 or more, use PM and further, if its 13 or more, subtract 12.
Another way to do it is to treat it as a string. But then you have to add enough leading zeros to get to length 6 and then break it into 2 character bits and convert each to an 'int' and that's way more work than just mod-ing by 100 and diving by 100 and 10,000.
There should never be a value in those two digit sections greater than 59.
Note
#radi8 noticed something I left out. I should have noted that the "/" (division) in the above algorithm has to be integer arithmetic for it to work right. Some programming languages offer integer arithmetic. JavaScript does not.
Since JavaScript uses floating point arithmetic, he subtracts off the number of seconds before dividing. Then a similar subtraction of the number of minutes fixes the next step.
You could also use Math.floor() after dividing to accomplish the same thing (since these are positive numbers).
Here is OP's code modified to do that:
$(function () {
var val1 = 41215,hr=0,min=0,sec=0;
sec = val1%100;
val1 = Math.floor(val1 / 100);
min = val1%100;
hr = Math.floor(val1 / 100);
// format the result. This example could show 1:1:1 instead of 01:01:01
tst2 = hr.toString()+':'+min.toString()+'.'+sec.toString();
alert(tst2.toString());
});
I started working on a timer to show how long people have been on my page. The problem is that instead of counting the seconds, it just keeps adding zeros to the end. Can anyone show me where I went wrong?
<script language="javascript">
<!--
var seconds = 0
var minutes = 0
document.getElementById('timer').innerHTML = '0'
function Timer() {
if ( seconds < 10 ) {
seconds = "0" + seconds
}
else if ( minutes < 10 ) {
minutes = "0" + minutes
}
else if ( seconds >= 59 ){
seconds = 0
minutes += 1
}
else
seconds += 1
document.getElementById('timer').innerHTML = "You've been on my blog for "+minutes+" : "+seconds+" minutes."
setTimeout("Timer()",1000)
}
//-->
</script>
Well yes, because you're concatenating a string. The + operator does both concatenation and addition.
"0" + foo // concatenate the string "0" and foo
0 + foo // add foo to 0 (given that both are numbers)
You're going about the timer the wrong way though. Your script is not guaranteed to execute on time, any slight delay in execution will give you accumulative the wrong value. The right way to do a timer is to take a fixed start time and use that as the base to calculate the difference every second or so.
var start = Date.now();
function timer() {
alert(((Date.now() - start) / 1000) + ' seconds elapsed');
}
setInterval(timer, 1000);
You're switching the variable type for seconds from being:
var seconds = 0 // integer type
....
seconds = "0" + seconds // now seconds is holding a string!
seconds (and minutes) should only be integers.
Also, just focus on the seconds. Later, divide it by 60 to display number of minutes. seconds % 60 will be the remaining number of sec.