moment.js shows wrong difference - javascript

I have a silly issue with time difference in moments.js.
Code to get time difference
var to = '2019-02-03 01:55:00'; //When counter ends
var start = moment(); //Current time, for this example assume is '2019-02-03 01:53:00'
var end = moment(to);
var seconds = end.diff(start, 'seconds', true); //get difference in seconds, the third params is to get not rounded, but since in toMMSS function I do parseInt is useless
var formatted = toMMSS(seconds);
function to format seconds:
var toMMSS = function (seconds) {
var sec_num = parseInt(seconds, 10);
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
return minutes+':'+seconds;
};
Now the expected output is 02:00, but some people get 02:05 or 02:07 or 02:03 but the output for '2019-02-03 01:55:00' - '2019-02-03 01:53:00' should be (logically) 02:00
P.S. moment.js defaults:
moment.tz.setDefault('Europe/Moscow');
moment.defaultFormat = "YYYY-MM-DD HH:mm:ss";
var end is also in that timezone.
I tried others ways of calculating the difference, but get the same result, it can be that on some PCs/Browser this is not accurate, if yes maybe there is a workaround to not rely on user PC time?
Any help appreciated.

Related

Time difference between 2 hours

I have beem looking for a code like this for a few days now. I did search a lot on the forum and found a bunch of threads about what I need but I couldn't get them to work (I have 0 expericnce in JS).
The code below does what I need, in a way.
It gives a negative value if the start time is, for example, 21:00 and the end time is 09:00.
Can anyone help me set it to positive? (I think it's related to beeing one day before, not sure thought).
<input type="time" id="start" value="21:00" >
<input type="time" id="end" value="09:00" >
<input id="diff">
<script>
var start = document.getElementById("start").value;
var end = document.getElementById("end").value;
document.getElementById("start").onchange = function() {diff(start,end)};
document.getElementById("end").onchange = function() {diff(start,end)};
function diff(start, end) {
start = document.getElementById("start").value; //to update time value in each input bar
end = document.getElementById("end").value; //to update time value in each input bar
start = start.split(":");
end = end.split(":");
var startDate = new Date(0, 0, 0, start[0], start[1], 0);
var endDate = new Date(0, 0, 0, end[0], end[1], 0);
var diff = endDate.getTime() - startDate.getTime();
var hours = Math.floor(diff / 1000 / 60 / 60);
diff -= hours * 1000 * 60 * 60;
var minutes = Math.floor(diff / 1000 / 60);
return (hours < 9 ? "0" : "") + hours + ":" + (minutes < 9 ? "0" : "") + minutes;
}
setInterval(function(){document.getElementById("diff").value = diff(start, end);}, 1000); //to update time every second (1000 is 1 sec interval and function encasing original code you had down here is because setInterval only reads functions) You can change how fast the time updates by lowering the time interval
</script>
PS: I found this code in here Difference between two html time inputs
Thanks in advance,
eLy
There are 2 possible solutions based on your requirement.
Start: 11AM, End: 9AM
If you want the output to be 2 hours,
var diff = Math.abs(endDate.getTime() - startDate.getTime());
If you want the output to be 22 hours,
var diff = endDate.getTime() - startDate.getTime();
if (diff < 0) {
diff += 24 * 1000 * 60 * 60;
}

How to transform a number that is counting up to HH:MM:SS?

I am counting up values on dynamically generated divs:
<div class="count">285489</div>
<div class="count">258569</div>
<div class="count">263548</div>
<div class="count">245856</div>
setInterval(function(){
$(".count").each(function() {
let el = $(this);
let time = Number(el.text()) + 1;
el.text(time);
});
}, 1000);
I want to transform those number into a HH:MM:SS format.
I have found the following snippet to achieve this:
String.prototype.toHHMMSS = function () {
var sec_num = parseInt(this, 10); // don't forget the second param
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) {hours = "0"+hours;}
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
return hours+':'+minutes+':'+seconds;
}
I modified the setInterval() function to use this function above
setInterval(function(){
$(".prod").each(function() {
let el = $(this);
let time = Number(el.text()) + 1;
time = time.toString();
el.text(time.toHHMMSS());
});
}, 1000);
However, when I run it, the values are incremented by only one second. After the increment, the values are showing NaN:NaN:NaN.
I don't understand. Why is it showing NaN when there should always be the new value available inside the div when it next gets incremented?
setInterval() is fired inside my Ajax complete function
All I need is those values to be displayed as HH:MM:SS instead of just a plain number.
Could anybody help?
After the first call to .toHHMMSS, all the div text become HH:MM:SS formatted. On the next iteration of .setInterval, we're attempting to parse an HH:MM:SS formatted string as an int, which fails and produces a NaN (because it's Not a Number). To fix this issue, you have two options:
Write a function to translate HH:MM:SS back to seconds, and then increment and run .toHHMMSS on that.
String.prototype.fromHHMMSS = function () {
if (isNaN(this)) {
var timeStrArr = this.split(":");
var hours = Integer.parseInt(timeStrArr[0]);
var minutes = Integer.parseInt(timeStrArr[1]);
var seconds = Integer.parseInt(timeStrArr[2]);
var totalSeconds = hours * 3600 + minutes * 60 + seconds
return totalSeconds;
} else {
return Number(this);
}
}
setInterval(function(){
$(".prod").each(function() {
let el = $(this);
let time = el.text().fromHHMMSS() + 1;
time = time.toString();
el.text(time.toHHMMSS());
});
}, 1000);
Work directly on the HH:MM:SS formatted string.
The issue is that after it performs once, the element text value is no longer numeric, but in your time format.
Try something like this:
<div class="count" data-time="285489"></div>
So the variable isn't changed when you set text. Then you can use it like this:
$(".prod").each(function() {
let el = $(this);
let time = Number(el.data("time")) + 1;
el.data("time", time);
time = time.toString();
el.text(time.toHHMMSS());
});
That may not be a complete solution, but you get the idea. After setting text now, the time will still be accessible in original format.
Modify below code in for each,
let txt = el.text();
if(txt.indexOf(':')){
txt = txt.replace(/:/g,'')
}
let time = Number(txt) + 1;
When code runs for the first time it replaces the original numbers with the HHMMSS representation. You need to either convert from HHMMSS to seconds or, just simpler, store the seconds. Also, having toHHMMSS() as method of the String object actually makes it harder to use in this case.
I'm storing seconds as properties of the DOM node for simplicity but of course you can use any storage you want.
function toHHMMSS(sec_num) {
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) {hours = "0"+hours;}
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
return hours+':'+minutes+':'+seconds;
}
let $count = $(".count");
$count.each(function() {
let el = $(this);
this.time = Number(el.text());
});
setInterval(function(){
$count.each(function() {
let el = $(this);
let time = ++this.time;
el.text(toHHMMSS(time));
});
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="count">285489</div>
<div class="count">258569</div>
<div class="count">263548</div>
<div class="count">245856</div>

Countdown can't be set to more than two days ahead

I have found a javascript code for a countdown timer in the internet and changed it a little bit to use it as I want.. It basically works fine, but as soon as I set the start date to more than 2 days ahead it doesn't to what it's supposed to. If I e.g. set it to three days ahead, as shown in the code below, it doesn't become a 72 hours countdown, but a 12 hours countdown.
I'm not sure whats the problem, because I can set up a 24 or a 48 hours countdown without any issues.
(function() {
var start = new Date;
start.setHours(18, 02, 20);
function pad(num) {
return ("0" + parseInt(num)).substr(-2);
}
function tick() {
var now = new Date;
var weekend = now.getDay();
if (now > start) {
start.setDate(start.getDate() + 3);
}
var remain = ((start - now) / 1000);
var hh = pad((remain / 60 / 60) % 60);
var mm = pad((remain / 60) % 60);
var ss = pad(remain % 60);
var distance = start - now;
document.getElementById('demo').innerHTML = hh + ":" + mm + ":" + ss
setTimeout(tick, 1000);
}
document.addEventListener('DOMContentLoaded', tick);
})();
The following line is the cause:
var hh = pad((remain / 60 / 60) % 60);
This caps the hours at 60 due to the % 60 (mod 60). 48 hours is less than 60 so it works. 72 hours will get translated to 12 (72 % 60 == 12).

Calculate difference between 2 dates in ISO format in JavaScript/TS

I have 2 dates in ISO format like so:
startDate: "2018-09-14T00:20:12.200Z"
endDate: "2018-09-16T00:18:00.000Z"
What I'm trying to do is calculate the difference between those 2 days. So with the given dates it would be 1 Day, 21 Hours, 47 Minutes and 40 Seconds (pardon me if the subtraction is not correct).
Tried to do using the following:
const start = new Date(startDate).getTime();
const end = new Date(endDate).getTime();
return Math.abs(end - start).toString();
However this doesn't seem to work.
Any clues?
The following works. Things to note:
getTime() is not needed as the new Date() constructor returns the time in milliseconds.
The date should always be in RFC2822 or ISO formats, else it becomes useless across various browsers, even while using moment.js.
If you can use moment.js, Get time difference using moment.
Refer this to know why only the standardized formats need to be used.
var unitmapping = {"days":24*60*60*1000,
"hours":60*60*1000,
"minutes":60*1000,
"seconds":1000};
function floor(value)
{
return Math.floor(value)
}
function getHumanizedDiff(diff)
{
return floor(diff/unitmapping.days)+" days "+
floor((diff%unitmapping.days)/unitmapping.hours)+" hours "+
floor((diff%unitmapping.hours)/unitmapping.minutes)+" minutes "+
floor((diff%unitmapping.minutes)/unitmapping.seconds)+" seconds "+
floor((diff%unitmapping.seconds))+" milliseconds";
}
console.log(getHumanizedDiff(new Date("2018-09-16T00:18:00.000Z") - new Date("2018-09-14T00:20:12.200Z")));
console.log(getHumanizedDiff(new Date("2018-09-16T00:18:00.000Z") - new Date("2018-09-04T00:20:02.630Z")));
console.log(getHumanizedDiff(new Date("2018-09-17T00:16:04.000Z") - new Date("2018-09-14T00:20:12.240Z")));
var startDate = "2018-09-14T00:20:12.200Z"
var endDate = "2018-09-16T00:18:00.000Z"
const start = new Date(startDate).getTime();
const end = new Date(endDate).getTime();
const milliseconds = Math.abs(end - start).toString()
const seconds = parseInt(milliseconds / 1000);
const minutes = parseInt(seconds / 60);
const hours = parseInt(minutes / 60);
const days = parseInt(hours / 24);
const time = days + ":" + hours % 24 + ":" + minutes % 60 + ":" + seconds % 60;
console.log(time)
yBrodsky's suggestion to use moment.js is probably the best idea, but if you're curious how to do the math here, it would go something like this:
const start = new Date(startDate).getTime();
const end = new Date(endDate).getTime();
let seconds = Math.round(Math.abs(end - start) / 1000); // We'll round away millisecond differences.
const days = Math.floor(seconds / 86400);
seconds -= days * 86400;
const hours = Math.floor(seconds / 3600);
seconds -= hours * 3600;
minutes = Math.floor(seconds / 60);
seconds -= minutes * 60;
This leaves you with hours, minutes, and seconds as numbers that you can format into a string result however you like.

String to date conversion not working correctly in Javascript

I need to get time difference in this format: "HH:MM:SS" using a Javascript.
I have tried this:
var diff = Date.parse( time2) - Date.parse( time1 );
var total_time = (diff / 1000 / 60 / 60) + ":" + (diff / 1000 / 60) + ":" + (diff / 1000);
and this:
var diff = new Date( time2) - new Date( time1 );
var total_time = (diff / 1000 / 60 / 60) + ":" + (diff / 1000 / 60) + ":" + (diff / 1000);
These are the values of time2 and time1:
time1: "2012-11-07 15:20:32.161"
time2: "2012-11-07 17:55:41.451"
And result I am getting in both cases is:
total_time= 0.5250819444444444:31.504916666666666:1890.295
Which you can see is not correct
I think you are getting wrong diff value because of the millisecond part in the date delimited by .. Its not being accepted correctly by the data parser.
Try using the date and time part excluding the milliseconds as below:
var diff = Date.parse(time2.split(".")[0]) - Date.parse( time1.split(".")[0]);
Also while you are getting wrong difference diff, your time computation is also wrong.
It should be:
var second = Math.floor(diff /1000);
//convert the seconds into minutes and remainder is updated seconds value
var minute = Math.floor(second /60);
second = second % 60;
//convert the minutes into hours and remainder is updated minutes value
var hour = Math.floor(minute/60);
minute = minute %60;
var total_time= hour+":" minute+":"+second;
You forgot to remove the number of milliseconds you already calculated from diff. Here is a very verbose example on how you do it in a propper way.
var time1 = "2012-11-07 15:20:32.161",
time2 = "2012-11-07 17:55:41.451",
SECOND = 1000,
MINUTE = SECOND* 60,
HOUR = MINUTE* 60;
var diff = new Date(time2) - new Date(time1);
var hours = Math.floor(diff / HOUR); // Calculate how many times a full hour fits into diff
diff = diff - (hours * HOUR); // Remove hours from difference, we already caluclated those
var minutes = Math.floor(diff / MINUTE); // Calculate how many times a full minute fits into diff
diff = diff - (minutes * MINUTE); // Remove minutes from difference
var seconds = Math.floor(diff / SECOND); // As before
diff = diff - (seconds * SECOND);
var rest = diff;
var total_time = hours + ":" + minutes + ":" + seconds + " " + rest ;
DEMO

Categories

Resources