Face NaN result when calculating time difference with javascript - javascript

I'm a newbie and still at the beginner level of PHP, Javascript, Codeigniter. I'm facing an unexpected result when I try to calculate the time difference between two 12 hours format time inputs.
Here is the HTML,JS
function hitungjam() {
var start = new Date($('#inputJammulai'));
var end = new Date($('#inputJamselesai'));
var s = start.toTimeString();
var e = end.toTimeString();
var diff = e - s;
var jam = Math.floor(diff/1000/60/60);
$('#inputSelisih').val(jam);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="form-group">
<div class="form-row">
<div class="col-md-4">
<label for="inputJammulai">Start</label>
<!-- <div class="form-label-group"> -->
<input type="time" name="inputJammulai" id="inputJammulai" class="form-control" required="required">
<!-- </div> -->
</div>
<div class="col-md-4">
<label for="inputJamselesai">End</label>
<!-- <div class="form-label-group"> -->
<input type="time" name="inputJamselesai" id="inputJamselesai" onchange="javascript: hitungjam();" class="form-control" required="required">
<!-- </div> -->
</div>
</div>
</div>
RESULT
start 09:00 AM
end 11:30 AM
the result is NaN.
WHAT EXPECTED RESULT
start at 09:00 AM, end at 11:30 AM, the result is 2,5
Oh FYI, before I write down this question I've done a search and tried many solutions given from StackOverflow but doesn't work on my problem. That's why I'm asking now.
Can anyone here help me to find out the solution? Thank you

Here is couple of things First in order to get the value from the input use val() which was missing. Secondly the output from the input is a string, so use parseInt to convert it to number before doing mathematical operations
Using split to get the numbers from the input since the input will be like 9:00 for 9:00AM or 23:30 for 11:30PM.
function hitungjam() {
var start = $('#inputJammulai').val();
var end = $('#inputJamselesai').val();
let diff = toMins(end) - toMins(start);
let jam = `${Math.floor(diff/60)}:${diff%60}`;
$('#inputSelisih').val(jam);
}
function toMins(time) {
let splitTime = time.split(":");
return (parseInt(splitTime[0], 10) * 60) + parseInt(splitTime[1], 10)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-group">
<div class="form-row">
<div class="col-md-4">
<label for="inputJammulai">Start</label>
<!-- <div class="form-label-group"> -->
<input type="time" name="inputJammulai" id="inputJammulai" class="form-control" required="required">
<!-- </div> -->
</div>
<div class="col-md-4">
<label for="inputJamselesai">End</label>
<!-- <div class="form-label-group"> -->
<input type="time" name="inputJamselesai" id="inputJamselesai" onchange="javascript: hitungjam();" class="form-control" required="required">
<!-- </div> -->
</div>
</div>
</div>
<input id='inputSelisih'>

I have done some modifications to your original code so you can get a base working example, I will try to explain some of these:
1) You was not getting the values from your inputs, you need to use .val() for this.
2) You can't make a difference between strings and expect a number as result. Instead of this, I have splited the obtained values from the inputs into hours and minutes. Then we create new Date objects with current time and set the respective hours and minutes to they. Finally, we can use difference within the Date.getTime() of each Date.
3) Math.floor() will return an integer, but you want a number with decimals, so instead of this I use toFixed(1) to get a decimal number (as string) with one digit after the dot.
Base Example:
function hitungjam()
{
var [h1, m1] = $('#inputJammulai').val().split(":");
var [h2, m2] = $('#inputJamselesai').val().split(":");
var start = new Date(), end = new Date();
start.setHours(h1);
start.setMinutes(m1);
end.setHours(h2);
end.setMinutes(m2);
var diff = end.getTime() - start.getTime();
var jam = (diff / 1000.0 / 60 / 60).toFixed(1);
$('#inputSelisih').val(jam);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="time" name="inputJammulai" id="inputJammulai" class="form-control" required="required">
<input type="time" name="inputJamselesai" id="inputJamselesai" onchange="javascript: hitungjam();" class="form-control" required="required">
<label>Difference (hours):<label>
<input type="text" id="inputSelisih">

Related

How can set an input time depending of another input time?

I'm trying to change link the times input. When I choose a hour in the eventStartTime, I would like to fill, depend of a time passing through the minutesToHours function (in minutes), the eventEndTime (an addition : the eventStartTime + the minutes I've added)
I have tried to do it by myself, but i didn't get any results :
$( document ).ready(function() {
$('#eventStart').on('input', function () {
var convertDuration = minuteToHours(6);
$('#eventEnd').val($(this).val() + moment(convertDuration).format('HH:mm'));
});
});
function minuteToHours(num) {
var hours = Math.floor(num / 60);
var minutes = num % 60;
return hours + ":" + minutes;
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="col-md-4">
<div class="form-group">
<label class="form-label" for="eventStart">Heure début</label>
<input class="form-control" id="eventStart" type="time">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label class="form-label" for="eventEnd">Heure Fin</label>
<input class="form-control" id="eventEnd" type="time">
</div>
</div>
Thanks for your help !

How do I make this conversion function work in both directions?

I'm new in JS and I have trouble to finish a converter only with inputs, I explain the problem !
We have two input, Meters and Feet. when I transmit a number to Feet I have the result in Meters. And I Want to do the same think with Meters . and vice versa
let metresEl = document.getElementById('inputMetres');
function LengthConverter(valNum) {
metresEl.value = valNum/3.2808;
}
<div class="container">
<div class="form-group">
<label>Feet</label>
<input type="number" id="inputFeet" placeholder="Feet" oninput="LengthConverter(this.value)" onchange="LengthConverter(this.value)" >
</div>
<div class="form-group">
<label>Metres</label>
<input type="number" id="inputMetres" placeholder="Metres">
</div>
</div>
You can add another parameter in the LengthConvertor function which will say the input unit (meter or feet) and convert it accordingly inside the function using if.
function LengthConverter(valNum, inputUnit) {
if(inputUnit === 'feet')
metresEl.value = valNum/3.2808;
if(inputUnit === 'meter')
feetsEL.value = valNum * 3.2808;
}
<div class="container">
<div class="form-group">
<label>Feet</label>
<input type="number" id="inputFeet" placeholder="Feet" oninput="LengthConverter(this.value,"feet")" onchange="LengthConverter(this.value,"feet")" >
</div>
<div class="form-group">
<label>Metres</label>
<input type="number" id="inputMetres" placeholder="Metres" oninput="LengthConverter(this.value,"meter")" onchange="LengthConverter(this.value,"meter")" >
</div>
</div>
Added inverse conversion:
let metresEl = document.getElementById('inputMetres');
let feetEl = document.getElementById('inputFeet');
function FeetToMetres(valNum) {
metresEl.value = valNum/3.2808;
}
function MetresToFeet(valNum) {
feetEl.value = 3.2808*valNum;
}
<div class="container">
<div class="form-group">
<label>Feet</label>
<input type="number" id="inputFeet" placeholder="Feet" oninput="FeetToMetres(this.value)" onchange="FeetToMetres(this.value)" >
</div>
<div class="form-group">
<label>Metres</label>
<input type="number" id="inputMetres" placeholder="Metres" oninput="MetresToFeet(this.value)" onchange="MetresToFeet(this.value)">
</div>
</div>
You can add a element.addEvenetListener to each input, and when it chances you get it's value, convert, and put in on the right input.
let metresEl = document.getElementById('inputMetres');
let feetsEl = document.getElementById('inputFeets');
metresEl.addEventListener('change', yourCode);
feetsEl.addEventListener('change', yourCode);
For exemple, if metres input changes, you convert to feets and add to feets input.

Is there a way to edit a javascript function to live update in a html form output?

I've written a working absence calculator using a HTML form and a javascript function. Unfortunately I need this to update to the output in real time and I cannot figure out how to do it without firing the function multiple times.
HTML
<form id="absence-form">
<div class="input">
<div id="title">Absence Calculator</div>
<div id="firstCell">
<div id="instruct">
Enter number of employees:
</div>
<input id="employees" type="text" name="employees">
<div id="secondCell">
<div id="instruct">
Enter average salary:
</div>
</div>
<input id="salary" type="text" name="salary">
<div id="thirdCell">
<div id="instruct">
Enter absence %:
</div>
</div>
<input id="absence" type="text" name="absence">
</div>
<div id="instruct">
<div id="output">Total salary (£):
<div id="totalSalary">
</div></div>
<div id="output">Monthly absence cost (£):
<span id="monthlyAbsence">
</span></div>
<div id="output">Annual absence cost (£):
<span id="absenceCost">
</span></div>
</div>
</div>
</form>
Javascript Function
function multiply() {
var employees = document.getElementById('employees').value;
var salary = document.getElementById('salary').value;
var totalSalary = parseInt(employees) * parseInt(salary);
var result1 = document.getElementById('totalSalary');
result1.innerHTML += totalSalary;
var absence = document.getElementById('absence').value;
var absenceCost = parseInt(totalSalary) / 100 * parseInt(absence);
var result2 = document.getElementById('absenceCost');
result2.innerHTML += absenceCost;
var monthlyAbsence = parseInt(absenceCost) / 12;
var result3 = document.getElementById('monthlyAbsence');
result3.innerHTML += monthlyAbsence;
}
});
Any pointers would be greatly appreciated.
You'll need to bind your function to the change event for the input elements.
This can be done a couple of ways:
Obtrusively (not recommended) with the element's onChange attribute (JSFiddle)
Non-obtrusively (preferred) with .on('change', function() {} }) (JSFiddle)
I'm assuming from the tag that you're using jQuery but you can achieve the same thing with vanilla JS using .addEventListener('change', callback, false) (JSFiddle)

User input from the DOM only returns NaN

I am attempting to build a depreciation calculator that uses user input fields to return an alert with the answer value.
If I do not use user input and simply set the variables to test values, the calculator works perfectly.
However when I request user input from the DOM the calculator only returns NaN. I tried to get the user input first with vanilla javascript and then jquery. I added console logs to try to find the problem and it showed that the variables were set to either 0 or undefined.
Can anyone here help me figure out why the user input isn't working?
// This is my attempt to get elements with JS, the only one that works is the button, I commented out the three that didn't work to attemmpt to fix with jquery
var assetValue = document.getElementById('assetValue').value;
var years = document.getElementById('years').value;
var currentYear = document.getElementById('currentYear').value;
var myBtn = document.getElementById('myBtn');
// This is my attempt with Jquery, none of it works, and I did not run it without commenting out the relevant vanilla JS
var assetValue = $("input#assetValue").val();
var years = $("input#years").val();
var currentYear = $("input#currentYear").val();
// Everything after here seems to be working fine, I used console logs to figure out where it messed up
//attach click event listener
myBtn.addEventListener('click', calc)
//The event object is then passed to this, I am assigning it the variable d
function calc(d) {
//prevent the default action - form submit / page refresh
d.preventDefault();
//Create derived variables
console.log(assetValue);
var remaining = (years - currentYear);
console.log(remaining);
var syDigits = ((years * (years + 1)) / 2);
console.log(syDigits);
var depreciation = (assetValue * (remaining / syDigits));
console.log(depreciation);
//Create Alert
alert("The depreciation in year " + currentYear + "is " + depreciation)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Depreciation Calculator</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="http://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<body>
<!-- The Form -->
<div class="container">
<form>
<div class="form-group">
<label for="exampleInputAsset">Asset Base</label> $
<input type="number" class="form-control" id="assetValue" placeholder="Enter An Integer Without Commas">
</div>
<div class="form-group">
<label for="exampleInputYears"># of Years</label>
<input type="number" class="form-control" id="years" placeholder="Enter An Integer Without Commas">
</div>
<div class="form-group">
<label for="exampleInputCurrentYear">Current Year</label>
<input type="number" class="form-control" id="currentYear" placeholder="Enter An Integer Without Commas">
</div>
<button type="submit" class="btn btn-primary" id="myBtn">Submit</button>
</form>
</div>
<script src="calculator.js"></script>
</body>
</html>
Try to convert your values to int:
From:
var assetValue = $("input#assetValue").val();
var years = $("input#years").val();
var currentYear = $("input#currentYear").val();
To:
var assetValue = parseInt($("input#assetValue").val());
var years = parseInt($("input#years").val());
var currentYear = parseInt($("input#currentYear").val());
I've made some refactoring:
use DOM instead of DOM.value
var assetValue = document.getElementById('assetValue');
var years = document.getElementById('years');
var currentYear = document.getElementById('currentYear');
var myBtn = document.getElementById('myBtn');
Parsing values using Number(<value>)
var assetValue = document.getElementById('assetValue');
var years = document.getElementById('years');
var currentYear = document.getElementById('currentYear');
var myBtn = document.getElementById('myBtn');
myBtn.addEventListener('click', calc)
function calc(event) {
event.preventDefault();
var remaining = Number(years.value) - Number(currentYear.value);
console.log(remaining);
var syDigits = (Number(years.value) * (Number(years.value) + 1)) / 2;
console.log(syDigits); // Victor's Algorithm
var depreciation = Number(assetValue.value) * (remaining / syDigits);
console.log(depreciation);
alert("The depreciation in year " + currentYear.value + " is " + depreciation)
return false;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<div class="container">
<form>
<div class="form-group">
<label for="exampleInputAsset">Asset Base</label> $
<input type="number" class="form-control" id="assetValue" placeholder="Enter An Integer Without Commas">
</div>
<div class="form-group">
<label for="exampleInputYears"># of Years</label>
<input type="number" class="form-control" id="years" placeholder="Enter An Integer Without Commas">
</div>
<div class="form-group">
<label for="exampleInputCurrentYear">Current Year</label>
<input type="number" class="form-control" id="currentYear" placeholder="Enter An Integer Without Commas">
</div>
<button type="submit" class="btn btn-primary" id="myBtn">Submit</button>
</form>
</div>

JavaScript validating datetime-local from form

I have an html form which allows for a taxi booking, but it shouldn't allow bookings back in time! so the time must be current or in the future.
Here is the form, I use datetime-local.
/* Here is the JavaScript validation for the datetime-local. */
var dateTime = document.getElementById("dateTime").value;
if (dateTime == "" || dateTime == null) {
booking.dateTime.focus();
document.getElementById("dateMessage").innerHTML = "Please select a date AND time, thankyou.";
return valid = false;
} else {
document.getElementById("destinationMessage").innerHTML = "";
}
```
<form id="booking" action="">
<div id="firstNameMessage" class="red"></div>
<span class="red">*</span>First Name:
<input type="text" name="firstName" id="firstName">
<br>
<div id="lastNameMessage" class="red"></div>
<span class="red">*</span>Last Name:
<input type="text" name="lastName" id="lastName">
<br>
<div id="numberMessage" class="red"></div>
<span class="red">*</span>Contact Number:
<input type="text" name="number" id="number">
<br>
<div id="unitMessage" class="red"></div>
Unit Number(optional):
<input type="text" name="unit" id="unit">
<br>
<div id="streetNumberMessage" class="red"></div>
<span class="red">*</span>Street Number:
<input type="text" name="streetNumber" id="streetNumber">
<br>
<div id="streetNameMessage" class="red"></div>
<span class="red">*</span>Street Name:
<input type="text" name="streetName" id="streetName">
<br>
<div id="pickupMessage" class="red"></div>
<span class="red">*</span>Suburb:
<input type="text" name="pickupSuburb" id="pickupSuburb">
<br>
<div id="destinationMessage" class="red"></div>
Destination Suburb<span class="red">*</span>:
<input type="text" name="destinationSuburb" id="destinationSuburb">
<br>
<div id="dateMessage" class="red"></div>
Pick-Up Date and Time<span class="red">*</span>:
<input type="datetime-local" name="dateTime" id="dateTime">
<br>
<br>
<input type="button" value="Submit"
onclick="getData('bookingprocess.php','message', firstName.value, lastName.value, number.value, unit.value, streetNumber.value, streetName.value, pickupSuburb.value, destinationSuburb.value, dateTime.value)" />
<input type="reset" value="Reset">
</form>
How can I make it check for being the current time or in the future? (Basically disabling past entries).
Please use input type = "date" instead of date-time. Probably no more supported by browsers.
Please refer this link
Now to set min date you cn use the following snippet
//Get today's date and split it by "T"
var today = new Date().toISOString().split('T')[0];
document.getElementById("dateTime").setAttribute('min', today);
DEMO
You can just compare dates by > and <. Make sure the dates in the same timezone though.
var dateTimeStr = document.getElementById("dateTime").value;
var dateTime = convertDateToUTC(new Date(dateTimeStr));
var now = new Date();
if (isNaN(date.getTime()) || date <= now) {
booking.dateTime.focus();
document.getElementById("dateMessage").innerHTML = "Please select a date AND time in the future, thankyou.";
return valid = false;
} else {
document.getElementById("destinationMessage").innerHTML = "";
}
function convertDateToUTC(date) {
return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
}
JS Fiddle
You should use a jquery or bootstrap calendar. It is ideal for this situation. It is also very easy for the user to pick up the date this way.
You have all configuration options in such calendars for e.g. assigning culture, date format, mindate, maxdate etc.
Also keep in mind to pick the date from server and set it as mindate in javascript since the datetime might be wrong on client computer.

Categories