I have few months java experience, but now I am trying to write my first javascript to validate a date input. I am not sure what is wrong in the code.
<label for="Start-date" class="label">Available start date</label>
<input type="text" onsubmit="isValidDate()" class="w-input" maxlength="256" name="Start-date" data-name="Start date" placeholder="dd/mm/yyyy" id="Start-date" th:value="${possibleStartDate}" />
<script>
var validDate = true;
function isValidDate(){
var dateString = document.getElementById("Start-date");
// First check for the pattern
if(!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString)){
validDate = false;
return;
}
// Parse the date parts to integers
var parts = dateString.split("/");
var day = parseInt(parts[1], 10);
var month = parseInt(parts[0], 10);
var year = parseInt(parts[2], 10);
// Check the ranges of month and year
if(year < 1000 || year > 3000 || month == 0 || month > 12){
validDate = false;
return;
}
var monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
// Adjust for leap years
if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)){
monthLength[1] = 29;
}
// Check the range of the day
if (!(day > 0 && day <= monthLength[month - 1])){
validDate = false;
return;
}else{
return;
}
};
if(!validDate){
alert("Invalid date!");
}
</script>
Also what is the better alternative to alert ? Something like a red small message under the textfield that the input is incorrect when submit button is pressed. I know it is better to have separate file for the javascript, but I am not sure where in the html to put the tags to link the file.
There were quite a few things which needed a little tweak:
var dateString = document.getElementById("Start-date") should be var dateString = document.getElementById("Start-date").value;
var day = parseInt(parts[1], 10); should be var day = parseInt(parts[0], 10); and var month = parseInt(parts[0], 10); should be var month = parseInt(parts[1], 10); to support dd/mm/yyyy
Inputs don't fire onsubmit unless they are a part of a form you can try onblur instead
I have wrapped the input with div with children indicating success/error to show the message better. (The messages are hidden shown using classes on the root div and supporting styles)
I have spearated out the validation of a date string from DOM manipulation so you can reuse the validation across multiple places
NOTES:
You may be better off setting the input type as date (the browser will open up a date picker if it supports it)
You can also optionally use libraries like momentjs to make common date operations a little easier.
/**
* Function which takes a string as an input and validates if it
* is a date in the dd/mm/yyyy format
* #param {string} dateString - The string representation of the date to validate
8 #returns {boolean} value indicating if the date is valid (true) or not (false)
*/
function isValidDate(dateString) {
var validDate = true;
// First check for the pattern
if (!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString)) {
return false;
}
// Parse the date parts to integers
var parts = dateString.split("/");
var day = parseInt(parts[0], 10);
var month = parseInt(parts[1], 10);
var year = parseInt(parts[2], 10);
if(isNaN(day) || isNaN(month) || isNaN(year)){
return false;
}
// Check the ranges of month and year
if (year < 1000 || year > 3000 || month < 1 || month > 12) {
return false;
}
var monthLength = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// Adjust for leap years
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
monthLength[1] = 29;
}
// Check the range of the day
if (!(day > 0 && day <= monthLength[month - 1])) {
return false;
}
return true;
};
/**
* Function which executes each time the input loses focus (onblur)
*/
function validateDate() {
// Get a reference to the container
var container = document.querySelector('.date');
// Clear stale error/success messages
container.className = container.className.replace('success', '');
container.className = container.className.replace('error', '');
// Get current value of input
var dateString = document.getElementById("Start-date").value;
// Test if the string is a valid date
var isValid = isValidDate(dateString);
// Update classess of container to show success/error
if (!isValid) {
container.className += ' error';
} else {
container.className += ' success';
}
}
div.date .error {
display: none;
background: red;
color: white;
}
div.date .success {
display: none;
background: darkgreen;
color: white;
}
div.date.success .success {
display: block;
}
div.date.error .error {
display: block;
}
<div class="date">
<label for="Start-date" class="label">Available start date</label>
<input type="text" onblur="validateDate()" class="w-input" maxlength="256" name="Start-date" data-name="Start date" placeholder="dd/mm/yyyy" id="Start-date" th:value="${possibleStartDate}" />
<div class="error">Please enter a valid date</div>
<div class="success">Date is valid</div>
</div>
If you're using the EcmaScript Date Time String Format, you can use the Date constructor. (Info
var dateString = document.getElementById("Start-date").value;
var validDate = !(isNaN( new Date(dateString) )
HTML5 also supports a type="date" in the <input> tag. This will prevent the browser from submitting the form if the date is invalid.
Also, I think you meant
var dateString = document.getElementById("Start-date").value;
Instead of
var dateString = document.getElementById("Start-date");
Because document.getElementById("Start-date") is an object.
Related
I'm trying to test to make sure a date is valid in the sense that if someone enters 2/30/2011 then it should be wrong.
How can I do this with any date?
One simple way to validate a date string is to convert to a date object and test that, e.g.
// Expect input as d/m/y
function isValidDate(s) {
var bits = s.split('/');
var d = new Date(bits[2], bits[1] - 1, bits[0]);
return d && (d.getMonth() + 1) == bits[1];
}
['0/10/2017','29/2/2016','01/02'].forEach(function(s) {
console.log(s + ' : ' + isValidDate(s))
})
When testing a Date this way, only the month needs to be tested since if the date is out of range, the month will change. Same if the month is out of range. Any year is valid.
You can also test the bits of the date string:
function isValidDate2(s) {
var bits = s.split('/');
var y = bits[2],
m = bits[1],
d = bits[0];
// Assume not leap year by default (note zero index for Jan)
var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// If evenly divisible by 4 and not evenly divisible by 100,
// or is evenly divisible by 400, then a leap year
if ((!(y % 4) && y % 100) || !(y % 400)) {
daysInMonth[1] = 29;
}
return !(/\D/.test(String(d))) && d > 0 && d <= daysInMonth[--m]
}
['0/10/2017','29/2/2016','01/02'].forEach(function(s) {
console.log(s + ' : ' + isValidDate2(s))
})
Does first function isValidDate(s) proposed by RobG will work for input string '1/2/'?
I think NOT, because the YEAR is not validated ;(
My proposition is to use improved version of this function:
//input in ISO format: yyyy-MM-dd
function DatePicker_IsValidDate(input) {
var bits = input.split('-');
var d = new Date(bits[0], bits[1] - 1, bits[2]);
return d.getFullYear() == bits[0] && (d.getMonth() + 1) == bits[1] && d.getDate() == Number(bits[2]);
}
I recommend to use moment.js. Only providing date to moment will validate it, no need to pass the dateFormat.
var date = moment("2016-10-19");
And then date.isValid() gives desired result.
Se post HERE
This solution does not address obvious date validations such as making sure date parts are integers or that date parts comply with obvious validation checks such as the day being greater than 0 and less than 32. This solution assumes that you already have all three date parts (year, month, day) and that each already passes obvious validations. Given these assumptions this method should work for simply checking if the date exists.
For example February 29, 2009 is not a real date but February 29, 2008 is. When you create a new Date object such as February 29, 2009 look what happens (Remember that months start at zero in JavaScript):
console.log(new Date(2009, 1, 29));
The above line outputs: Sun Mar 01 2009 00:00:00 GMT-0800 (PST)
Notice how the date simply gets rolled to the first day of the next month. Assuming you have the other, obvious validations in place, this information can be used to determine if a date is real with the following function (This function allows for non-zero based months for a more convenient input):
var isActualDate = function (month, day, year) {
var tempDate = new Date(year, --month, day);
return month === tempDate.getMonth();
};
This isn't a complete solution and doesn't take i18n into account but it could be made more robust.
var isDate_ = function(input) {
var status = false;
if (!input || input.length <= 0) {
status = false;
} else {
var result = new Date(input);
if (result == 'Invalid Date') {
status = false;
} else {
status = true;
}
}
return status;
}
this function returns bool value of whether the input given is a valid date or not. ex:
if(isDate_(var_date)) {
// statements if the date is valid
} else {
// statements if not valid
}
I just do a remake of RobG solution
var daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
var isLeap = new Date(theYear,1,29).getDate() == 29;
if (isLeap) {
daysInMonth[1] = 29;
}
return theDay <= daysInMonth[--theMonth]
This is ES6 (with let declaration).
function checkExistingDate(year, month, day){ // year, month and day should be numbers
// months are intended from 1 to 12
let months31 = [1,3,5,7,8,10,12]; // months with 31 days
let months30 = [4,6,9,11]; // months with 30 days
let months28 = [2]; // the only month with 28 days (29 if year isLeap)
let isLeap = ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
let valid = (months31.indexOf(month)!==-1 && day <= 31) || (months30.indexOf(month)!==-1 && day <= 30) || (months28.indexOf(month)!==-1 && day <= 28) || (months28.indexOf(month)!==-1 && day <= 29 && isLeap);
return valid; // it returns true or false
}
In this case I've intended months from 1 to 12. If you prefer or use the 0-11 based model, you can just change the arrays with:
let months31 = [0,2,4,6,7,9,11];
let months30 = [3,5,8,10];
let months28 = [1];
If your date is in form dd/mm/yyyy than you can take off day, month and year function parameters, and do this to retrieve them:
let arrayWithDayMonthYear = myDateInString.split('/');
let year = parseInt(arrayWithDayMonthYear[2]);
let month = parseInt(arrayWithDayMonthYear[1]);
let day = parseInt(arrayWithDayMonthYear[0]);
My function returns true if is a valid date otherwise returns false :D
function isDate (day, month, year){
if(day == 0 ){
return false;
}
switch(month){
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
if(day > 31)
return false;
return true;
case 2:
if (year % 4 == 0)
if(day > 29){
return false;
}
else{
return true;
}
if(day > 28){
return false;
}
return true;
case 4: case 6: case 9: case 11:
if(day > 30){
return false;
}
return true;
default:
return false;
}
}
console.log(isDate(30, 5, 2017));
console.log(isDate(29, 2, 2016));
console.log(isDate(29, 2, 2015));
It's unfortunate that it seems JavaScript has no simple way to validate a date string to these days. This is the simplest way I can think of to parse dates in the format "m/d/yyyy" in modern browsers (that's why it doesn't specify the radix to parseInt, since it should be 10 since ES5):
const dateValidationRegex = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
function isValidDate(strDate) {
if (!dateValidationRegex.test(strDate)) return false;
const [m, d, y] = strDate.split('/').map(n => parseInt(n));
return m === new Date(y, m - 1, d).getMonth() + 1;
}
['10/30/2000abc', '10/30/2000', '1/1/1900', '02/30/2000', '1/1/1/4'].forEach(d => {
console.log(d, isValidDate(d));
});
Hi Please find the answer below.this is done by validating the date newly created
var year=2019;
var month=2;
var date=31;
var d = new Date(year, month - 1, date);
if (d.getFullYear() != year
|| d.getMonth() != (month - 1)
|| d.getDate() != date) {
alert("invalid date");
return false;
}
function isValidDate(year, month, day) {
var d = new Date(year, month - 1, day, 0, 0, 0, 0);
return (!isNaN(d) && (d.getDate() == day && d.getMonth() + 1 == month && d.getYear() == year));
}
I'm trying to put a leap year checker in my Age calculator. It worked for sometime and now it outputs "This is a leap year" every time I select a date. What am I doing wrong?? Thank you!
var year;
function ageCalculator() {
var userinput = document.getElementById("DOB").value;
var dob = new Date(userinput);
if (userinput == null || userinput == '') {
document.getElementById("message").innerHTML = "**Choose a date please!";
return false;
} else {
//calculate month difference from current date in time
var month_diff = Date.now() - dob.getTime();
//convert the calculated difference in date format
var age_dt = new Date(month_diff);
//extract year from date
var year = age_dt.getUTCFullYear();
calYear();
//now calculate the age of the user
var age = Math.abs(year - 1970);
//display the calculated age
return document.getElementById("result").innerHTML =
"Age is: " + age + " years. ";
}
}
function calYear() {
var yr = year;
var yr = document.getElementsByName("year");
if (yr % 400 == 0 || (yr % 100 != 0 && yr % 4 == 0)) {
window.alert("This is not leap!");
} else {
window.alert("This is a leap!");
}
}
<input type="text" id="DOB" />
<button type="button" onclick="ageCalculator()">Calculate</button>
<span id="message"></span><br/>
<span id="result"></span>
document.getElementsByName("year") is a Collection not an Element value! Also, Element.value returns always a string - and it's your task as a developer to convert strings (or know typecasting by heart) to an integer or a float as necessary.
Don't put specifics into a function (like i.e: document.getElementById etc) make it reusable!
Avoid using variables that end up polluting the global Window scope (var year). At some point try to console.log(window.year) and you'll see why.
Don't call a function calYear() ? if it returns a string. Instead call it properly: isLeap() and do what it says! Return a Boolean value.
Only at the point you use/call that function in your UI - decide there the appropriate string you want to show. Don't limit yourself.
Be always careful while using new Date(someUserInput) where someUserInput might be an invalid ISO8601 string. You can easily get false positives.
PS: Date.now() - dob.getTime() cannot by any means be what your comment says: "calculate month difference" that's absolutely not true - Be careful when writing your comments and when naming your functions.
/**
* #param {integer} year
* #return {boolean} - True if year is leap year
*/
const isLeap = (year) => (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
/**
* #param {string} DOBString - A valid ISO8601 dateString
* #return {integer} - Age
*/
const calcAge = (DOBString) => {
const UTC_DOB = new Date(DOBString);
if (!DOBString || isNaN(UTC_DOB)) return;
const UTC_today = new Date();
const m = UTC_today.getUTCMonth() - UTC_DOB.getUTCMonth(); // Month diff
let age = UTC_today.getUTCFullYear() - UTC_DOB.getUTCFullYear();
if (m < 0 || (m === 0 && UTC_today.getUTCDate() < UTC_DOB.getUTCDate())) age--;
return age;
};
// UI/Page/View specific scripts:
const EL_DOB = document.querySelector("#DOB");
const EL_result = document.querySelector("#result");
const EL_leap = document.querySelector("#leap");
const UI_showAgeResult = () => {
const age = calcAge(EL_DOB.value);
const UTC_DOB = new Date(EL_DOB.value);
const is_leap = isLeap(UTC_DOB.getUTCFullYear());
EL_result.textContent = age ? age : "Insert a valid date";
EL_leap.textContent = is_leap ? "Born on a leap year! so cool" : "";
};
// Do it on input Event
EL_DOB.addEventListener("input", UI_showAgeResult);
// And if needed on page init
UI_showAgeResult();
<input id="DOB" type="text" value="2000-02-29"/>
<span id="result"></span><br>
<span id="leap"></span>
Important:
notice that if user Date Of Birth is say "2000-02-29", and say today's date is "2001-02-28" the result age will be arguably-correctly 0.
Only if date is "2001-03-01" will result as 1 y of age.
Kudos:
Slightly modified #naveen answer's code for calculating dates diff → age.
I suggest you look at this version
Calculate age given the birth date in the format YYYYMMDD
To fix YOUR code we need to pass the year to the function and not try to use a non-existing year field
If there was such a field, you could access its value with document.querySelector("[name=year]").value since document.getElementsByName is a collection and the value would be document.getElementsByName("year")[0].value
So what did I do?
passed the DOB year to the leap function
calculated the age from the year of the date difference
I tested with 2000-02-29 and 2001-02-28
NOTE the script ALSO works with 02/29/2016 but not with 29/02/2016 (European format)
var year;
function ageCalculator() {
var userinput = document.getElementById("DOB").value;
var dob = new Date(userinput);
if (isNaN(dob)) {
document.getElementById("message").innerHTML = "**Choose a date please!";
return false;
} else {
//extract year from date
var year = dob.getFullYear();
console.log(year)
testLeap(year);
//calculate difference from current date in milliseconds
var date_diff = Date.now() - dob.getTime();
//convert the calculated difference in date format
var age_dt = new Date(date_diff);
//now calculate the age of the user
var age = Math.abs(1970 - age_dt.getFullYear());
//display the calculated age
return document.getElementById("result").innerHTML =
"Age is: " + age + " years. ";
}
}
function testLeap(yr) {
const isLeap = (yr % 400 == 0 || (yr % 100 != 0 && yr % 4 == 0))
alert(isLeap ? "This is a leap!" : "This is not a leap!");
}
<input type="text" id="DOB" />
<button type="button" onclick="ageCalculator()">Calculate</button>
<span id="message"></span><br/>
<span id="result"></span>
If you only need a function to check if the input year is a leap year or not, you can use Date object:
function isLeapYear(year) {
// year, monthIndex, day
return new Date(year, 1, 29).getFullYear() === year;
}
this is function to check if this year is leap year
function isLeapYear(year){
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
isLeapYear(2000) //true
isLeapYear(2001) // false
EDIT:
so the problem is in document.getElementsByName("year")
i think you should have a HTML named year which is have the year value
<input type="number" name="year" />
Here's another Method I can make sure it will works
function ageCalculator() {
var userinput = document.getElementById("DOB").value;
var dob = new Date(userinput);
if (userinput == null || userinput == '') {
document.getElementById("message").innerHTML = "**Choose a date please!";
return false;
} else {
//calculate month difference from current date in time
var month_diff = Date.now() - dob.getTime();
//convert the calculated difference in date format
var age_dt = new Date(month_diff);
//extract year from date
var year = age_dt.getUTCFullYear();
calYear(year);
//now calculate the age of the user
var age = Math.abs(year - 1970);
//display the calculated age
return document.getElementById("result").innerHTML =
"Age is: " + age + " years. ";
}
}
function calYear(yr) {
if (yr % 400 == 0 || (yr % 100 != 0 && yr % 4 == 0)) {
window.alert("This is not leap!");
} else {
window.alert("This is a leap!");
}
}
Try updating the callYear if condition assuming
yr> 1000 and yr < 8000
function calYear(yr) {
if ((yr % 4 === 0 && yr % 100 !== 0) || yr % 400 === 0 ) {
window.alert("This is not leap!");
} else {
window.alert("This is a leap!");
}
}
I'm trying to test to make sure a date is valid in the sense that if someone enters 2/30/2011 then it should be wrong.
How can I do this with any date?
One simple way to validate a date string is to convert to a date object and test that, e.g.
// Expect input as d/m/y
function isValidDate(s) {
var bits = s.split('/');
var d = new Date(bits[2], bits[1] - 1, bits[0]);
return d && (d.getMonth() + 1) == bits[1];
}
['0/10/2017','29/2/2016','01/02'].forEach(function(s) {
console.log(s + ' : ' + isValidDate(s))
})
When testing a Date this way, only the month needs to be tested since if the date is out of range, the month will change. Same if the month is out of range. Any year is valid.
You can also test the bits of the date string:
function isValidDate2(s) {
var bits = s.split('/');
var y = bits[2],
m = bits[1],
d = bits[0];
// Assume not leap year by default (note zero index for Jan)
var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// If evenly divisible by 4 and not evenly divisible by 100,
// or is evenly divisible by 400, then a leap year
if ((!(y % 4) && y % 100) || !(y % 400)) {
daysInMonth[1] = 29;
}
return !(/\D/.test(String(d))) && d > 0 && d <= daysInMonth[--m]
}
['0/10/2017','29/2/2016','01/02'].forEach(function(s) {
console.log(s + ' : ' + isValidDate2(s))
})
Does first function isValidDate(s) proposed by RobG will work for input string '1/2/'?
I think NOT, because the YEAR is not validated ;(
My proposition is to use improved version of this function:
//input in ISO format: yyyy-MM-dd
function DatePicker_IsValidDate(input) {
var bits = input.split('-');
var d = new Date(bits[0], bits[1] - 1, bits[2]);
return d.getFullYear() == bits[0] && (d.getMonth() + 1) == bits[1] && d.getDate() == Number(bits[2]);
}
I recommend to use moment.js. Only providing date to moment will validate it, no need to pass the dateFormat.
var date = moment("2016-10-19");
And then date.isValid() gives desired result.
Se post HERE
This solution does not address obvious date validations such as making sure date parts are integers or that date parts comply with obvious validation checks such as the day being greater than 0 and less than 32. This solution assumes that you already have all three date parts (year, month, day) and that each already passes obvious validations. Given these assumptions this method should work for simply checking if the date exists.
For example February 29, 2009 is not a real date but February 29, 2008 is. When you create a new Date object such as February 29, 2009 look what happens (Remember that months start at zero in JavaScript):
console.log(new Date(2009, 1, 29));
The above line outputs: Sun Mar 01 2009 00:00:00 GMT-0800 (PST)
Notice how the date simply gets rolled to the first day of the next month. Assuming you have the other, obvious validations in place, this information can be used to determine if a date is real with the following function (This function allows for non-zero based months for a more convenient input):
var isActualDate = function (month, day, year) {
var tempDate = new Date(year, --month, day);
return month === tempDate.getMonth();
};
This isn't a complete solution and doesn't take i18n into account but it could be made more robust.
var isDate_ = function(input) {
var status = false;
if (!input || input.length <= 0) {
status = false;
} else {
var result = new Date(input);
if (result == 'Invalid Date') {
status = false;
} else {
status = true;
}
}
return status;
}
this function returns bool value of whether the input given is a valid date or not. ex:
if(isDate_(var_date)) {
// statements if the date is valid
} else {
// statements if not valid
}
I just do a remake of RobG solution
var daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
var isLeap = new Date(theYear,1,29).getDate() == 29;
if (isLeap) {
daysInMonth[1] = 29;
}
return theDay <= daysInMonth[--theMonth]
This is ES6 (with let declaration).
function checkExistingDate(year, month, day){ // year, month and day should be numbers
// months are intended from 1 to 12
let months31 = [1,3,5,7,8,10,12]; // months with 31 days
let months30 = [4,6,9,11]; // months with 30 days
let months28 = [2]; // the only month with 28 days (29 if year isLeap)
let isLeap = ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
let valid = (months31.indexOf(month)!==-1 && day <= 31) || (months30.indexOf(month)!==-1 && day <= 30) || (months28.indexOf(month)!==-1 && day <= 28) || (months28.indexOf(month)!==-1 && day <= 29 && isLeap);
return valid; // it returns true or false
}
In this case I've intended months from 1 to 12. If you prefer or use the 0-11 based model, you can just change the arrays with:
let months31 = [0,2,4,6,7,9,11];
let months30 = [3,5,8,10];
let months28 = [1];
If your date is in form dd/mm/yyyy than you can take off day, month and year function parameters, and do this to retrieve them:
let arrayWithDayMonthYear = myDateInString.split('/');
let year = parseInt(arrayWithDayMonthYear[2]);
let month = parseInt(arrayWithDayMonthYear[1]);
let day = parseInt(arrayWithDayMonthYear[0]);
My function returns true if is a valid date otherwise returns false :D
function isDate (day, month, year){
if(day == 0 ){
return false;
}
switch(month){
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
if(day > 31)
return false;
return true;
case 2:
if (year % 4 == 0)
if(day > 29){
return false;
}
else{
return true;
}
if(day > 28){
return false;
}
return true;
case 4: case 6: case 9: case 11:
if(day > 30){
return false;
}
return true;
default:
return false;
}
}
console.log(isDate(30, 5, 2017));
console.log(isDate(29, 2, 2016));
console.log(isDate(29, 2, 2015));
It's unfortunate that it seems JavaScript has no simple way to validate a date string to these days. This is the simplest way I can think of to parse dates in the format "m/d/yyyy" in modern browsers (that's why it doesn't specify the radix to parseInt, since it should be 10 since ES5):
const dateValidationRegex = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
function isValidDate(strDate) {
if (!dateValidationRegex.test(strDate)) return false;
const [m, d, y] = strDate.split('/').map(n => parseInt(n));
return m === new Date(y, m - 1, d).getMonth() + 1;
}
['10/30/2000abc', '10/30/2000', '1/1/1900', '02/30/2000', '1/1/1/4'].forEach(d => {
console.log(d, isValidDate(d));
});
Hi Please find the answer below.this is done by validating the date newly created
var year=2019;
var month=2;
var date=31;
var d = new Date(year, month - 1, date);
if (d.getFullYear() != year
|| d.getMonth() != (month - 1)
|| d.getDate() != date) {
alert("invalid date");
return false;
}
function isValidDate(year, month, day) {
var d = new Date(year, month - 1, day, 0, 0, 0, 0);
return (!isNaN(d) && (d.getDate() == day && d.getMonth() + 1 == month && d.getYear() == year));
}
I saw this fiddle for validating mm/dd/yyyy or mm-dd-yyyy but I would like to validate yyyy-mm-dd hh:mm:ss format also how do I ensure that today is lesser than from date with the yyyy-mm-dd hh:mm:ss format?.
this is how I have initiated my date time picker..
$("#startDate, #endDate").datetimepicker({ dateFormat: 'yyyy-mm-dd hh:mm:ss'});
Please do help me to get this done.
Thanks
The date format that you have specified is ISO 8601. Most modern browsers support Date parsing of this string format. So you can do something like this.
Javascript
var iso8601 = "2013-02-01 10:00:00",
userDate = new Date(iso8601),
today = new Date(),
dateTime,
date,
time,
value;
// check is valid date
if (isNaN(userDate)) {
alert("invalid userDate");
}
// check if userDate is before today
if (userDate.getDate() < today.getDate()) {
alert("userDate is in past");
}
// check the string specifically matches "yyyy-mm-dd hh:mm:ss" and is valid
function isGregorianLeapYear(year) {
return year % 400 === 0 || year % 100 !== 0 && year % 4 === 0;
}
function daysInGregorianMonth(year, month) {
var days;
if (month == 2) {
days = 28;
if (isGregorianLeapYear(year)) {
days += 1;
}
} else {
days = 31 - ((month - 1) % 7 % 2);
}
return days;
}
if (typeof iso8601 !== "string") {
alert("not an iso8601 string");
} else {
dateTime = iso8601.split(" ");
if (dateTime.length !== 2) {
alert("missing date or time element");
} else {
date = dateTime[0].split("-");
if (date.length !== 3) {
alert("incorrect number of date elements");
} else {
value = +date[0];
if (date[0].length !== 4 || value < -9999 || value > 9999) {
alert("year value is incorrect");
}
value = +date[1];
if (date[1].length !== 2 || value < 1 || value > 12) {
alert("month value is incorrect");
}
value = +date[2];
if (date[2].length !== 2 || value < 1 || value > daysInGregorianMonth(+date[0], +date[1])) {
alert("day value is incorrect");
}
}
time = dateTime[1].split(":");
if (time.length !== 3) {
alert("incorrect number of time elements");
} else {
value = +time[0];
if (time[0].length !== 2 || value < 0 || value > 23) {
alert("hour value is incorrect");
}
value = +time[1];
if (time[1].length !== 2 || value < 0 || value > 59) {
alert("minute value is incorrect");
}
value = +time[2];
if (time[2].length !== 2 || value < 0 || value > 59) {
alert("second value is incorrect");
}
}
}
}
console.log(userDate);
console.log(today);
jsFiddle
Checking yyyy-mm-dd hh:mm:ss strings against each other is pretty easy because they're already in order; you can forget about what base the numbers are in and simply do < or > as in string comparison. This may not work with other dates.
function compISOZDate(d1, d2) { // d1 is
if (d1 < d2) return -1; // smaller
if (d1 === d2) return 0; // the same
/* else */ return 1; // bigger
}
Validating dates is a bit more complicated, because the number of days in months can change. You can ignore this fact and just test for digits, but I prefer meeting half way, introducing upper limits.
function verifyMyDate(d) {
var re = /^\d{4}-(0[1-9]|1[0-2])-([0-2]\d|3[01]) (0\d|1[01]):[0-5]\d:[0-5]\d$/;
// yyyy - MM - dd hh : mm : ss
return re.test(d);
}
So for example using it
var d1 = '2013-10-07 11:58:26',
d2 = '2012-06-14 19:22:03';
// check
if (!verifyMyDate(d1)) throw new Error('Invalid date: ' + d1);
if (!verifyMyDate(d2)) throw new Error('Invalid date: ' + d2);
// compare
compISOZDate(d1, d2); // 1, d1 is bigger than d2
// also
compISOZDate(d2, d1); // -1
compISOZDate(d1, d1); // 0
Now all that is left is to get the value from your inputs.
Change your RegExp inside the ValidateDate function to below code
function ValidateDate(dtValue)
{
var dtRegex = new RegExp(/\b\d{4}[\/-]\d{1,2}[\/-]\b\d{1,2} (0\d|1[01]):[0-5]\d:[0-5]\d$\b/);
return dtRegex.test(dtValue);
}
try this and let me know, same way u can validate the hh:mm:ss also
For 24 hour variation, instead of AM/PM, use:
regex = new RegExp(^\d{4}-(0[1-9]|1[0-2])-([0-2]\d|3[01]) (0\d|1\d|2[0-3]):[0-5]\d:[0-5]\d$);
This is mine I wrote and works fine :
function validateDate(dtValue) {
// Format expected dd/mm/aaaa or dd-mm-aaaa (French Date)
// Accept also d/m/aaaa or d-m-aaaa (ok for MySQL Database to have one number only for days and months)
// Before the insert into database I will convert to aaaa-mm-jj or aaaa-m-j
var dtRegex = new RegExp(/\b(0?[1-9]|([1-2]?[0-9]|3[0-1]))[\/-]([0]?[1-9]|1[0-2])[\/-]\b\d{4} ([0-1]?[0-9]|2[0-3]):[0-5]\d$\b/);
// Accept range => (01 to 31) (/ or -) (01 to 12) (/ or -) (4 numbers) space (00 to 23) : (00 to 59)
var bValidateDate= dtRegex.test(dtValue);
// Test if bValidateDate true, test and throw out (accepted from regex expression) :
// 30/02, 31/02, 31/04, 31/06, 31/09, 31/11
// 30-02, 31-02, 31-04, 31-06, 31-09, 31-11
// Get the 5 first characters
var sFebruary29= dtValue.substring(0, 5);
if (bValidateDate)
{
var aOfDateErrors= ["30/02", "31/02", "31/04", "31/06", "31/09", "31/11", "30-02", "31-02", "31-04", "31-06", "31-09", "31-11"];
if (aOfDateErrors.indexOf(sFebruary29) > -1)
{
bValidateDate= false;
}
}
// Then, if bValidateDate is still true (good format)
// check if the date is a leap year to accept 29/02 or 29-02
// And finally, my customer asked me to have a year between 2017 and now
if (bValidateDate)
{
// Get the year
var sYear= dtValue.substring(6, 10);
// Customer's constraints
var bYearCustomerOK= ((parseInt(sYear) >= 2017) && (parseInt(sYear) <= new Date().getFullYear()));
// I promise, this is the "last test'em all !"
var bFinalDate= (bYearCustomerOK) && (sYear % 400 === 0 || sYear % 100 !== 0 && sYear % 4 === 0) && ((sFebruary29 == "29/02") ||(sFebruary29 == "29-02"));
if (! bFinalDate)
{
bValidateDate= false;
}
}
return bValidateDate;
}
Please, let me know if you find a bad date :)
Possible Duplicate:
Detecting an “invalid date” Date instance in JavaScript
I was using the following to detect a valid date:
var text = $('#Date').val();
var date = Date.parse(text);
if (isNaN(date)) {
// Invalid date
}
But found that Date.parse thinks the following are valid dates (mm/dd/yyyy)
2/30/2011
11/31/2011
Any other way to detect invalid dates when the number of days surpasses the total number of
days in the month?
UPDATE: An even larger problem is that the jQuery validation plugin doesn't detect this as an invalid date either!
SOLUTION:
Based on #Guffa's comments I have created the following function to validate dates:
function validDate(text) {
var date = Date.parse(text);
if (isNaN(date)) {
return false;
}
var comp = text.split('/');
if (comp.length !== 3) {
return false;
}
var m = parseInt(comp[0], 10);
var d = parseInt(comp[1], 10);
var y = parseInt(comp[2], 10);
var date = new Date(y, m - 1, d);
return (date.getFullYear() == y && date.getMonth() + 1 == m && date.getDate() == d);
}
To check if a date is valid you can parse the components of the date, create a Date object from it, and check if the components in the data is the same as the parsed components. If you create a Date object from compnents that are out of range, the values will flow over to the next/previous period to create a valid date.
For example, new Date(2011,0,42) will create an object that contains the date 2/11/2011 instead of 1/42/2011.
By parsing the components instead of the full date you will also get around the problem with different date formats. My browser will for example expect a date format like y-m-d rather than d/m/y.
Example:
var text = '2/30/2011';
var comp = text.split('/');
var m = parseInt(comp[0], 10);
var d = parseInt(comp[1], 10);
var y = parseInt(comp[2], 10);
var date = new Date(y,m-1,d);
if (date.getFullYear() == y && date.getMonth() + 1 == m && date.getDate() == d) {
alert('Valid date');
} else {
alert('Invalid date');
}
Demo: http://jsfiddle.net/Guffa/UeQAK/
If your date format is fixed as M/D/YYYY, you could re-format the parsed date and see if it matches the input:
var d = new Date(Date.parse(str))
return str === (d.getMonth()+1)+'/'+d.getDate()+'/'+d.getYear();
However, that won't tolerate whitespace or zero-padded numbers.
If you don't need to keep the user's input exactly, you could just reformat the date anyway and pretend that was what they typed.
But if you can't do that either, I'd parse out the components myself using a RegExp and then compare them to values from the Date methods.
You could write a script to do this manually:
function checkDate(day, month) {
if ((month == 4 || month == 6 || month == 9 || month == 11) && day < 30) {
alert("Date is valid")
}
else if (month == 2 && day <= 28) {
alert("Date is valid")
}
else if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day <= 31) {
alert("Date is valid")
}
else {
alert("Date is in-valid")
}
}
Of course, you would also need something to look out for leap years, but just remember that any year divisible by 4 and not by 100 is a leap year unless the first two digits of the year are divisible by 4. That should be easy to include in this function.
The example is wrong
the correct is
if ((month == 4 || month == 6 || month == 9 || month == 11) && day <= 30)
<= instead of =
But the example are great!
A simple, intrinsic way to achieve this can be:
let dateObj = document.getElementById('Date');
if (dateObj.validity.badInput) {
// show error message
}
Now some date formatting can be done, but HTML date-picker event has properties like badInput and valid to check invalid dates.