I have a form with a date and time field, the date field consists of 3 fields: day, month and year. And time field consists of 2 fields, hour and minute.
I want to show an alert if the date is older than 2 months and 60 hours.
HTML:
<div class="container-date">
<div class="date_day">
<input type="text" maxlength="2" name="input_day" id="input_day" value="">
</div>
<div class="date_month">
<input type="text" maxlength="2" name="input_month" id="input_month" value="">
</div>
<div class="date_year>
<input type="text" maxlength="4" name="input_year" id="input_year" value="">
</div>
</div>
<div class="container-time">
<div class="time_hour>
<input type="text" maxlength="2" name="input_hour" id="input_hour" value="">
</div>
<div class="time_minute">
<input type="text" maxlength="2" name="input_minute" id="input_minute" value="">
</div>
</div>
I can do it with one field only for date, but have now 3 fields that I need.
I tried something like this:
jQuery(document).ready(function($){
var day = $('#input_day');
var month = $('#input_month');
var year = $('#input_year');
var today = new Date();
var currentMonth = today.getMonth();
month.on("input change", function() {
if ((today.getMonth() + 11) - (this + 11) > 4) {
console.log('test');
}
});
});
I'd suggest you to parse the form date, create the comparison date according to the expected period and then return if the formDate is greater than comparisonDate.
Please, let me know if the code below is according to what you expected:
function getFormDate() {
const formYear = $("#input_year").val();
const formMonth = $("#input_month").val() - 1;
const formDay = $("#input_day").val();
const formHour = $("#input_hour").val();
const formMinute = $("#input_minute").val();
return new Date(formYear, formMonth, formDay, formHour, formMinute, 0, 0)
}
function getComparisonDate() {
const today = new Date()
let comparisonDate = new Date()
comparisonDate.setMonth(today.getMonth() - 2)
comparisonDate.setHours(today.getHours() - 60)
return comparisonDate
}
function thereIsMissingValue() {
let anyMissing = false;
const inputs = $(".container-date input, .container-time input")
inputs.each(function () {
if (!$(this).val())
anyMissing = true
});
return anyMissing
}
function displayMessage() {
const formDate = getFormDate()
const comparisonDate = getComparisonDate()
$("#min-allowed-date").text(comparisonDate.toLocaleString())
const isOlderThanComparison = formDate < comparisonDate
$(".older-date").toggle(isOlderThanComparison)
const isInTheFuture = formDate > new Date()
$(".future-date").toggle(isInTheFuture)
const isValidDate = !isOlderThanComparison && !isInTheFuture
$(".valid-date").toggle(isValidDate)
}
function calculate() {
if (thereIsMissingValue()) {
$(".container-date-validation").hide()
return
}
$(".container-date-validation").show()
displayMessage()
}
$('#input_year, #input_month, #input_day, #input_hour, #input_minute').change(function () { calculate(); })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-date">
<div class="date_day">
<label>Day</label>
<input type="text" maxlength="2" name="input_day" id="input_day" value="">
</div>
<div class="date_month">
<label>Month</label>
<input type="text" maxlength="2" name="input_month" id="input_month" value="">
</div>
<div class="date_year">
<label>Year</label>
<input type="text" maxlength="4" name="input_year" id="input_year" value="">
</div>
</div>
<div class="container-time">
<div class="time_hour">
<label>Hour</label>
<input type="text" maxlength="2" name="input_hour" id="input_hour" value="">
</div>
<div class="time_minute">
<label>Minute</label>
<input type="text" maxlength="2" name="input_minute" id="input_minute" value="">
</div>
</div>
<div class="container-date-validation" style="display:none">
<p class="older-date" style="display:none">Invalid date. Only dates after
<span id="min-allowed-date"></span> are allowed.
</p>
<p class="future-date" style="display:none">Invalid date. It doesn't allow dates in the future.</p>
<p class="valid-date">This is a valid date</p>
</div>
If you go with milliseconds :
2 months is 5184000000
60 hours is 216000000
total : 5400000000
the wantedDate will be new Date(year, month, day)
var wantedDate = new Date(year,month,day); // will create a date from the inputs
wantedDate.getTime() // will convert to miliseconds
and if you convert the wanted date to milliseconds you can easily find out
wantedDate < Date.now() && wantedDate > (Date.now() - 5400000000)
I really like using Moment.js for things like this. It uses much more human-readable code, like so:
const moment = require('moment'); // assumes you install Moment as a node module
const month = $('#input_month');
const day = $('#input_day');
const year = $('#input_year');
const hour = $('#input_hour');
const minute = $('#input_minute');
const checkDate = () => {
const inputDate = moment(month.val() + '/' + day.val() + '/' + year.val() + ' ' + hour.val() + ':' + minute.val(), "MM-DD-YYYY HH:mm");
const expDate = moment.subtract(2, "months").subtract(60, "hours");
if (moment(inputDate).isBefore(expDate, "minute") {
// do something
}
}
month.on('change', checkDate);
You'll also need to ensure you're getting usable values from your inputs. I suggest using number input types or select menus to restrict input options.
Related
This is a corporate massage job quote calculator.
From the user, we collect:
Start time
End time
Number of clients needing a massage
We then use those variables in conjunction with our business rules of time needed per person and hourly rate for a therapist to determine how many therapists are needed and how much it will cost the client to staff those therapists.
When ran, my console displays an error message "timeStr.split is not a function". I thought there was an issue with the .map() method but I've tried resolving to no avail. I am new to JS and could really use some help, please. Here is the code
HTML
<body>
<label for="starttime">Start Time</label><br>
<input id="starttime" type="time" name="starttime" placeholder="Start time"><br>
<label for="endtime">End Time</label><br>
<input id="endtime" type="time" name="endtime" placeholder="End time"><br>
<label for="clients"># of people needing massage</label><br>
<input id="clients" type="number" name="clients" id=""><br>
<input type="button" value="Submit" id="inputbtn" onclick="calc()">
</body>
JS
/*User Inputs*/
const start = document.getElementById("starttime").value;
const end = document.getElementById("endtime").value;
const people = document.getElementById("clients").value;
let timeStart = new Date("01/02/2020" + start);
let timeEnd = new Date("01/02/2020"+end);
/*constants*/
const rate = 80;
const allot = "00:20:00";
/*Time converter*/
function convTime(timeStr){
arr = timeStr.split(":");
arr = arr.map(Number=> Number);
let theHours = arr[0];
let theMinutes = arr[1]/60;
let timeDec = theHours+theMinutes;
return timeDec;
}
/*formulas*/
const ogTime = timeEnd - timeStart;
const givenTime = convTime(ogTime);
const convAllot = convTime(allot)
const realTime = people*convAllot;
const therapists = realTime/givenTime;
const price = therapists*rate*givenTime;
console.log(price);
Moved declare variables of users inputs into Calc() Method to get the value after user insert it, not only on Document Load
use MomentJs Library to calc diff dates and get Hours, minutes, ...
set inputs default values for DEMO only
/*constants*/
var dateStr = "01/02/2020";
const rate = 80;
const allot = moment(new Date(dateStr)).add("+20m"); // 20 minutes
/*Time converter*/
function convTime(t) {
t = moment(t);
let theHours = t.format('h');
let theMinutes = t.format('mm');
let timeDec = Number(theHours) + Number(theMinutes);
return timeDec;
}
function calc() {
/*User Inputs*/
const start = document.getElementById("starttime").value;
const end = document.getElementById("endtime").value;
const people = document.getElementById("clients").value;
var timeStart = new Date(dateStr + " " + start);
var timeEnd = new Date(dateStr + " " + end);
/*formulas*/
const ogTime = moment(timeEnd).diff(timeStart);
const givenTime = convTime(ogTime);
const convAllot = convTime(allot);
const realTime = people * convAllot;
const therapists = realTime / givenTime;
const price = therapists * rate * givenTime;
console.log(price);
}
calc(); // call it on load -- remove this if you want onclick only
<label for="starttime">Start Time</label><br>
<input id="starttime" type="time" name="starttime" placeholder="Start time" value="07:00"><br>
<label for="endtime">End Time</label><br>
<input id="endtime" type="time" name="endtime" placeholder="End time" value="08:00"><br>
<label for="clients"># of people needing massage</label><br>
<input id="clients" type="number" name="clients" value="1"><br>
<input type="button" value="Submit" id="inputbtn" onclick="calc()">
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
Hi I'm very novice at Javascript so apologies for asking naff questions.
This piece of code is returning a Nan when it should retrieve days elapsed.
Is the second function causing the issue?
Here it is:
<body>
<script>
function elapsedTime(date1, date2) {
var start = new Date(date1);
var startMilli = start.getTime();
var end = new Date(date2);
var endMilli = end.getTime();
var elapsed = (endMilli - startMilli);
alert(millisToDaysHoursMinutes(elapsed));
}
function millisToDaysHoursMinutes(millis) {
var seconds = millis / 1000;
var totalMinutes = seconds / 60;
var minutesPerDay = 60 * 24;
var days = totalMinutes / minutesPerDay;
return days;
}
</script>
<form>
Start:<input type="text" name="date1" value="dd/m/year" /><br>
End: <input type="text" name="date2" value="dd/m/year" />
<input type="button" name="button1" onclick="elapsedTime(date1.value, date2.value)" value="Get Elapsed Time" />
</form>
</body>
You need to ensure that the dates entered are valid else you'll get a NaN (Not a Number). Use input type=date and make them required then you can easily check that they're valid before calling your date diff function.
EG:
function elapsedTime(date1, date2) {
var start = new Date(date1);
var startMilli = start.getTime();
var end = new Date(date2);
var endMilli = end.getTime();
var elapsed = (endMilli - startMilli);
alert(millisToDaysHoursMinutes(elapsed));
}
function millisToDaysHoursMinutes(millis) {
var seconds = millis / 1000;
var totalMinutes = seconds / 60;
var minutesPerDay = 60 * 24;
var days = totalMinutes / minutesPerDay;
return days;
}
var date1 = document.querySelector("input[name=date1]"),
date2 = document.querySelector("input[name=date2]"),
button1 = document.querySelector("input[name=button1]");
button1.addEventListener("click", function() {
var date1valid = date1.checkValidity();
var date2valid = date2.checkValidity();
if (date1valid && date2valid) {
elapsedTime(date1.value, date2.value);
} else {
alert("Please provide both dates!");
}
});
<form>
Start:<input type="date" name="date1" required="required" value="dd/m/year" /><br> End: <input type="date" name="date2" required="required" value="dd/m/year" />
<input type="button" name="button1" value="Get Elapsed Time" />
</form>
You should use input type date to make your code work:
<form>
Start:<input type="date" name="date1" /><br>
End: <input type="date" name="date2" />
<input type="button" name="button1" onclick="elapsedTime(date1.value, date2.value)" value="Get Elapsed Time" />
</form>
I'm trying to display and update a child's age through a MM/dd/YYYY textbox, and simple int values in year(s) and month(s) textboxes.
So if a child had a birthday of: 02/03/2015, and I'm comparing against today's date of 03/07/2018, the Year textbox should say 3 and the month textbox should say 1
If you were to change the year value to 5, the DoB value should change to 02/03/2013.
If you were to then change the month value to 9, the DoB value should change to 05/03/2012.
If I were to change the DoB value, the Year and Month textbox should also change to the appropriate values.
The day value should be persisted, and changed to 01 when it can't.
I would like to of course account for odd date arithmetic.
What I have so far in my C# MVC app is that I have a ChildViewModel object with these properties:
DateTime? DateOfBirth
public int AgeMonths
public int AgeYears
On my view, I have a textbox for each of these values.
<div class="row">
<div class="form-group">
#Html.LabelFor(m => m.DateOfBirth, new { #class = "control-label" })
#Html.TextBoxFor(m => m.DateOfBirth, "{0:MM/dd/yyyy}", new { #class = "form-control", placeholder = "Child's Date of Birth", onchange = "determineAge(this.id, null, null)" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.AgeYears, new { #class = "control-label" })
#Html.TextBoxFor(m => m.AgeYears, new { #class = "form-control", placeholder = "x years and...", onchange = "determineAge(null, this.id, null)" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.AgeMonths, new { #class = "control-label" })
#Html.TextBoxFor(m => m.AgeMonths, new { #class = "form-control", placeholder = "...y months old", onchange = "determineAge(null, null, this.id)" })
</div>
</div>
Here is my JavaScript so far, slightly altered to work in the snippet, using a little bit of moment.js v2.21.0
https://jsfiddle.net/RyanTaite/fak22xrf
The snippet below is effectively the same code:
function determineAge(dobId, ageYearsId, ageMonthsId) {
///<summary>Updates the Date of Birth, Years, and/or Months text box(es) based on what's passed in. It's likely terribly written and I'd welcome a rewrite by someone better at date math. Dependant on moment.js</summary>
var dobValue = null;
var yearValue = null;
var monthValue = null;
var today = new Date();
// Update DOB, AgeYears, and AgeMonths based on who was changed
if (dobId !== null) {
dobValue = new Date(document.getElementById(DateOfBirth.value));
var ageInMonths = today.getMonth() - dobValue.getMonth() + (12 * (today.getFullYear() - dobValue.getFullYear()));
yearValue = Math.floor(ageInMonths / 12);
monthValue = ageInMonths % 12;
document.getElementById('AgeYears').value = yearValue;
document.getElementById('AgeMonths').value = monthValue;
} else if (ageYearsId !== null) {
yearValue = document.getElementById('AgeYears').value;
monthValue = document.getElementById('AgeMonths').value;
dobValue = new Date(document.getElementById('DateOfBirth').value);
dobValue.setFullYear(today.getFullYear() - yearValue);
document.getElementById('DateOfBirth').value = dobValue.toLocaleDateString();
} else if (ageMonthsId !== null) {
dobValue = new moment(new Date());
monthValue = parseInt(document.getElementById('AgeMonths').value);
yearValue = parseInt(document.getElementById('AgeYears').value);
var dayValue = new moment(document.getElementById('DateOfBirth').value, "MMDDYYYY").get('date');
var totalMonths = monthValue + (yearValue * 12);
dobValue.subtract(totalMonths, "months");
// This is the proper way to set the day value of a moment object, you have to chain your way there
dobValue.year(dobValue.get('year')).month(dobValue.get('month')).date(dayValue);
document.getElementById('DateOfBirth').value = moment(dobValue._d).format("MM/DD/YYYY");
}
}
<script src="https://momentjs.com/downloads/moment.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div class="form-group">
<div class="control-label">Date of Birth</div>
<input class="form-control" id="DateOfBirth" placeholder="Child's Date of Birth" onchange="determineAge(this.id, null, null)"></input>
</div>
<div class="form-group">
<div class="control-label">Years</div>
<input class="form-control" id="AgeYears" placeholder="x years and..." onchange="determineAge(null, this.id, null)"></input>
</div>
<div class="form-group">
<div class="control-label">Months</div>
<input class="form-control" id="AgeMonths" placeholder="...y months old" onchange="determineAge(null, null, this.id)"></input>
</div>
</div>
It's buggy and likely terribly written, so I'd love some help with this.
I believe I fixed it using diff and general moment properties more, as Matt's comment suggested.
If nothing else, it's cleaner and closer to what I wanted.
I welcome anyone's suggestions or edits to improve this.
function determineAge(dobId, ageYearsId, ageMonthsId) {
///<summary>Updates the Date of Birth, Years, and/or Months text box(es) based on what's passed in. Dependant on moment.js</summary>
var dobValue = null;
var yearValue = null;
var monthValue = null;
var today = new moment();
// Update DOB, AgeYears, and AgeMonths based on who was changed
if (dobId !== null) {
dobValue = new moment(document.getElementById('DateOfBirth').value, "MMDDYYYY");
yearValue = new moment().diff(dobValue, 'years');
monthValue = new moment().diff(dobValue, 'month') % 12;
document.getElementById('AgeYears').value = yearValue;
document.getElementById('AgeMonths').value = monthValue;
} else if (ageYearsId !== null || ageMonthsId !== null) {
yearValue = parseInt(document.getElementById('AgeYears').value);
monthValue = parseInt(document.getElementById('AgeMonths').value);
dobValue = new moment(document.getElementById('DateOfBirth').value, "MMDDYYYY");
const ageInMonths = (yearValue * 12) + (monthValue);
const todayMinusMonths = today.subtract(ageInMonths, 'months');
const dayValue = dobValue.date();
dobValue = todayMinusMonths;
dobValue.date(dayValue);
document.getElementById('DateOfBirth').value = dobValue.format("MM/DD/YYYY");
}
}
<script src="https://momentjs.com/downloads/moment.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div class="form-group">
<div class="control-label">Date of Birth</div>
<input class="form-control" id="DateOfBirth" placeholder="MM/dd/YYYY" onchange="determineAge(this.id, null, null)">
</div>
<div class="form-group">
<div class="control-label">Years</div>
<input class="form-control" id="AgeYears" placeholder="x years and..." onchange="determineAge(null, this.id, null)">
</div>
<div class="form-group">
<div class="control-label">Months</div>
<input class="form-control" id="AgeMonths" placeholder="...y months old" onchange="determineAge(null, null, this.id)">
</div>
</div>
i have 2 time pickers in my page like
<div class="form-group">
<input class="time ui-timepicker-input" id="FromTime" name="FromTime" type="text" value="" autocomplete="off">
</div>
<div class="form-group">
<input class="time ui-timepicker-input" id="ToTime" name="FromTime" type="text" value="" autocomplete="off">
</div>
$(document).ready(function () {
$('#ToTime').timepicker();
$('#FromTime').timepicker();
});
Now i want to set ToTime = FromTime + 1 hour
To raise FromTime value change event and i use the code
$('#FromTime').timepicker().on('changeTime.timepicker', function(e) {
//how to get selected time here
//set ToTime value with a difference of 1 hour ie if 12:30 am selected set ToTime as 1:30 am
});
Try this code
Demo
JS
$(document).ready(function () {
$('#FromTime').timepicker({
defaultTime: false
});
});
var HoursToAdd = 2;
$('#FromTime').timepicker().on('changeTime.timepicker', function (e) {
var meridian = e.time.meridian
var hours = e.time.hours
var minutes = e.time.minutes
var seconds = e.time.seconds
var NewTime;
if (meridian == 'AM') {
NewTime = new Date('', '', '', hours, minutes, seconds)
} else if (meridian == 'PM') {
NewTime = new Date('', '', '', (hours + 12), minutes, seconds)
}
NewTime.setHours(NewTime.getHours() + HoursToAdd)
$('#ToTime').timepicker({
defaultTime: NewTime.getHours() + " : " + NewTime.getMinutes()
});
});
I have set up a page that holds 2 pickadates. One for a start date and one for an end date.
I also have a number of checkboxes, labeled:
1 Day, 1 Month, 1 Year
Once the user selects a date from the first pickadate. They can either pick a second date from the second pickadate.
But I wish to offer a second alternative. Where if they check 1 day, the 2nd pickadate will be the result of 1 day + the 1st pickdate. Likewise for the 1 month and 1 year checkbox.
Is there anyway to accomplish this?
My current HTML is:
<div class="inputdata">
<label>Timeframe:</label>
<span>
<div class="section__block section__block--scoped">
From:
<fieldset>
<input type="text" id="input_from">
</fieldset>
To:
<fieldset>
<input type="text" id="input_to">
</fieldset>
</div>
</span>
<div class="clear"></div>
<span><input id="x_timeframe" type="date" name="date_timeframe"></span>
<label></label>
<span id="x_timeframe_checkboxes">
<input type="radio" name="a_timeframe" id="radio4" value="d" class="css-checkbox"/>
<label for="radio4" class="css-label">1 Day</label>
<input type="radio" name="a_timeframe" id="radio5" value="w" class="css-checkbox" />
<label for="radio5" class="css-label">1 Week</label>
<input type="radio" name="a_timeframe" id="radio6" value="m" class="css-checkbox" />
<label for="radio6" class="css-label">1 Month</label>
<input type="radio" name="a_timeframe" id="radio8" value="n" class="css-checkbox" />
<label for="radio8" class="css-label">None</label>
</span>
</div>
Just for familiarity, the js includes:
<script src="/x/js/calendar/pickadate.js-3.4.0/lib/picker.js"></script>
<script src="/x/js/calendar/pickadate.js-3.4.0/lib/picker.date.js"></script>
<script src="/x/js/calendar/pickadate.js-3.4.0/lib/picker.time.js"></script>
<script src="/x/js/calendar/pickadate.js-3.4.0/lib/legacy.js"></script>
<script src="/x/js/calendar/pickadate.js-3.4.0/demo/scripts/main.js"></script>
<script src="/x/js/calendar/pickadate.js-3.4.0/lib/pickadate1454.js"></script>
+1 Day on #from_picker
var from_picker = $('#input_from').pickadate(), to_picker = $('#input_from').pickadate();
from_picker.pickadate('picker').on('set', function (event) {
if (event.select) {
to_picker.pickadate('picker').set('select', from_picker.pickadate('picker').get('select').pick + 1 * 24 * 60 * 60 * 1000);
}
});
You could use only JS to do the trick, by getting the value from you date field and transform in a js Date and the add the Days or Moths.
I always create 7 functions, to work with date in JS: addSeconds, addMinutes, addHours, addDays, addWeeks, addMonths, addYears.
You can see an example here: http://jsfiddle.net/tiagoajacobi/YHA8x/
How to use:
var now = new Date();
console.log(now.addWeeks(3));
This are the functions:
Date.prototype.addSeconds = function(seconds) {
this.setSeconds(this.getSeconds() + seconds);
return this;
};
Date.prototype.addMinutes = function(minutes) {
this.setMinutes(this.getMinutes() + minutes);
return this;
};
Date.prototype.addHours = function(hours) {
this.setHours(this.getHours() + hours);
return this;
};
Date.prototype.addDays = function(days) {
this.setDate(this.getDate() + days);
return this;
};
Date.prototype.addWeeks = function(weeks) {
this.addDays(weeks*7);
return this;
};
Date.prototype.addMonths = function (months) {
var dt = this.getDate();
this.setMonth(this.getMonth() + months);
var currDt = this.getDate();
if (dt !== currDt) {
this.addDays(-currDt);
}
return this;
};
Date.prototype.addYears = function(years) {
var dt = this.getDate();
this.setFullYear(this.getFullYear() + years);
var currDt = this.getDate();
if (dt !== currDt) {
this.addDays(-currDt);
}
return this;
};