x
• Status: Solved
• Priority: Medium
• Security: Public
• Views: 70

# Calculate difference between 2 durations

I have a web page where the user can enter times - such as "34.56" (34 seconds, 56 hundredths), "1:07.32" (1 minute, 7 seconds, 32 hundredths), up to 59:59.99.

For each input field there is a defined "Minimum" and "Maximum" allowed time, in the same format as above.

I want to validate that the entered time is within the Minimum / Maximum time range.

I am trying to use the "duration" feature in moment.js - but I can't get it to work, nor can I find enough information about "durations".

I have this:

``````
\$('.timeInput').blur(function () {
var enteredVal = \$(this).val();
if (enteredVal == '') return;

var mReq = moment.duration("40.99");
var mEnteredVal = moment.duration(enteredVal);
var timeDiff = mEnteredVal.asMilliseconds - mReq.asMilliseconds;

if (timeDiff > 0) {
} else {
}
}
``````

However, it doesn't work. The above is a test version that just checks if the entered time is greater than the mReq value. Once I've got that working, I will extend it to check the time is within the min / max values.

The min and max values will eventually come from hidden fields on the page.
0
ascendinternet
• 5
• 5
1 Solution

Developer & EE ModeratorCommented:
First, make sure your spelling is exact and also your closing brackets match.  I don't think yours did and that may be from copy/pasting.

1. Convert input to a number
2. Declare variable you want to test against
3. Use duration of minutes
4. Compare entered value against your test variable

http://jsbin.com/sozifuxavo/edit?html,output
``````<!DOCTYPE html>
<html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<body>
<input class="timeInput" placeholder="TimeInput">
<input>
<script src="https://code.jquery.com/jquery-3.0.0.js"></script>
<script src="https://cdn.jsdelivr.net/momentjs/2.14.1/moment-with-locales.min.js"></script>
<script>
\$(function(){
\$('.timeInput').blur(function () {
var enteredVal = \$(this).val();
enteredVal = Number(enteredVal); // convert tonumber
var testVal = moment.duration(49.99, 'minutes');
newEnteredVal=moment.duration(enteredVal,'minutes');
alert(newEnteredVal + ' : '+ testVal);
if(newEnteredVal > testVal){
} else {
}

});

});
</script>
</body>
</html>
``````
0

Author Commented:
Sorry, the code in my post was only part of the code I had, so I may have missed a bracket or two!

I don't understand why I should use a duration of minutes - the times entered might be minutes, seconds and hundredths (e.g. 1:07.43) - or might just be seconds and hundredths (e.g. 34.59)

Your sample works for seconds and hundredths (34.59) but not if it goes to minutes (1:07.43).
0

Developer & EE ModeratorCommented:
Using duration, you need to make sure your comparison matches.

http://jsbin.com/beyakixuca/1/edit?html,output
``````<!DOCTYPE html>
<html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<body>

<div></div>
<script src="https://code.jquery.com/jquery-3.0.0.js"></script>
<script src="https://cdn.jsdelivr.net/momentjs/2.14.1/moment-with-locales.min.js"></script>
<script>
\$(function(){
var x = moment.duration('23:59:30.2');
var y = moment.duration('24:00:24.2');
if (x > y){
\$('div').text('greater');
} else {
\$('div').text('less');
}

});
</script>
</body>
</html>
``````
0

Author Commented:
By "you need to make sure your comparison matches" - do you mean the format of the time needs to match?

Sometimes, the min / max values might only be seconds & hundredths, sometimes it will be minutes, second and hundredths - so the formatting needs to be dynamic / flexible!?

Is there another / easier way to do it, without using moment.js?
0

Developer & EE ModeratorCommented:
One way or another, you will need to know if "23" is an hour, minute, second or fraction or just a great center.

If you are presented with "21.5" you may assume that is 21 seconds and 5 tenths.  So format that as "0:00:21.5"

What you can't do is see a 1 and 21 and let the black box figure out the user meant the 1 as an hour and 21 as minutes.  It is up to you to format the data no matter if you use moment or pure javascript date.
0

Developer & EE ModeratorCommented:
To clarify,

<input value ="1">  then compare against 40.99 where the user meant 1 as an hour and your comparison is against 40 seconds and 99 tenths.
0

Author Commented:
Sorry, I have already dealt with formatting the input, so if you type 4099 it gets formatted as "40.99", if you type 10765 it gets formatted as "1:07.65".

I will need to deal with "stupid" inputs like "1" or "999999" but for now, I want to get it working for valid inputs.
0

Author Commented:
OK, I now have this which appears to be working:

``````        \$('.timeInput')
.blur(function () {
var enteredVal = \$(this).val().toString();
if (enteredVal == '') return;

var inputId = this.id;
var fromVal = \$('#from_' + inputId).val().toString();
var toVal = \$('#to_' + inputId).val().toString();

var statusIcon = \$('#status_' + inputId);
if (mEnteredVal >= mReqFrom && mEnteredVal <= mReqTo) {
statusIcon.attr("class", "fa fa-check");
} else {
statusIcon.attr("class", "fa fa-times");
}
});

var pattern = "00:00:00.00";

var timeLen = strTime.length;

return pattern.substr(0, pattern.length - timeLen) + strTime;
}
``````

The HTML input tag has a maxlength="8". Also the input is formatted using this plugin - http://igorescobar.github.io/jQuery-Mask-Plugin/ (code not shown).

Can the code be improved, for safety and/or performance and/or code reduction purposes?
0

Developer & EE ModeratorCommented:
>Can the code be improved, for safety

This is all client side.  If you are eventually going to use this to post data to your db, you want to make sure you scrub and check data server side even if you validate on the client.

>Can the code be improved, for performance and/or code reduction purposes
If it is working, go with it.  In production you will want to compress all your javascript/jquery code.  I'm sure there are some things that can be done to make this more efficient like using pure js.  For the the likes of Google and Facebook, small changes can make a very big difference.   For your purposes, you may find the page will load almost the same expanded like this or minified.
0

Commented:
You can also just use a custom function to convert to milliseconds - a lot smaller than including the entire moment.js library
``````function timeToMS(value)
{
var current = min = sec = 0;
for(var i = 0; i < value.length; i++) {
c = value[i];
if (c == ':') {
min = current;
current = 0;
}
else if (c == '.') {
sec = current;
current = 0;
}
else {
current = current * 10 + c * 1;
}
}

return (min*60000 + sec * 1000 + current);
}
``````
Working sample here
0

Author Commented:
The key issue turned out to be that the format of the comparisons needed to match. I ensured both values were formatted to "00:00:00.000".
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.