I have tried two popular answers from Detecting an "invalid date" Date instance in JavaScript for checking valid dates. I tested both of them in IE8 – Unfortunately both are disappointing. See it here http://jsfiddle.net/Lijo/uzSU6/2/
Is there a better JavaScript code that will work in IE8 + Chrome + Firefox?
Note: To my surprise, it doesn't work well in Firefox too...
CONDITION
The date format is expected to be US date format with slashes (/)
CODE
isValidDateCheck2('12/33/2012') ;
isValidDateCheck1('12/12/2012') ;
function isValidDateCheck1(d)
{
alert(Object.prototype.toString.call(d));
if ( Object.prototype.toString.call(d) !== "[object Date]" )
{
alert('Not Valid');
}
if(!isNaN(d.getTime()))
{
alert(d.getTime());
}
}
function isValidDateCheck2(d)
{
var timestamp=Date.parse(d);
alert(timestamp);
if (isNaN(timestamp)==false)
{
var date=new Date(timestamp);
alert(date);
}
}
EDIT
#mplungjan approach (first suggested) is listed in http://jsfiddle.net/Lijo/uzSU6/7/. This was failed in IE8 for one scenario - http://jsfiddle.net/Lijo/uzSU6/12/.
You seem to be conflating two things here. Valid date objects and valid dates. These are not the same problem.
The question you linked to answers how to test for validity of date objects (whether a date object is an "invalid date" instance). Invalid date objects are generated when you use invalid parameters when constructing them: new Date('?')
What you want is to test if a date string conforms to a predefined date format. This is an entirely different problem that should not be solved by using only date objects.
Generally speaking, there are a couple of reasons for this; the first is that the browsers will helpfully compute overflow months/days/time to the correct date: new Date(2012,0,290) === Oct 06 2012.
Secondly because the parser may be locale dependent (mm/dd vs. dd/mm?). When the date is parsed by the browser my locale may cause it roll it to my timezone/DST thus skewing it and messing up detection (.getDate may now return next day over). Even worse, this may only occur across some timezones at certain parts of the year.
I strongly encourage using a library like date.js to handle this stuff because dates are much harder than you think! If you absolutely must validate by hand, then I recommend doing it in detail like this:
function isValidDate (str) {
// parse to numbers
const rm = str.split('/');
const m = 1 * rm[0];
const d = 1 * rm[1];
const y = 1 * rm[2];
if (isNaN(m * d * y)) {
return false;
}
// day can't be 0
if (d < 1) {
return false;
}
// month must be 1-12
if (m < 1 || m > 12) {
return false;
}
// february
if (m === 2) {
const isLeapYear = ((y % 4 === 0) && (y % 100 !== 0)) || (y % 400 === 0);
// leap year
if (isLeapYear && d > 29) {
return false;
}
// non-leap year
if (!isLeapYear && d > 28) {
return false;
}
}
// test any other month
else if (
((m === 4 || m === 6 || m === 9 || m === 11) && d > 30) ||
((m === 1 || m === 3 || m === 5 || m === 7 || m === 8 || m === 10 || m === 12) && d > 31)) {
return false;
}
return true;
}
As a jsFiddle: http://jsfiddle.net/3pMPp/1/
As a jsPerf: http://jsperf.com/silly-date-valiation
This will handle actual dates and give you the chance to find what part of the date was invalid - using the DATE OBJECT
NOTE: several browsers will happily parse what seems to be an invalid date and make a date object out of it. For example 02/29/2013 will parse as 1st of March 2013, hence my test to see if the parts entered made sense when used in an actual date.
DEMO
Tested in
Win7:
Chrome 23 (only one to give isNaN on the first date)
IE 9
Win XP:
FX 17
IE 8
Safari 5
Opera 11 and 12
function isValidDateCheck(dString) {
// test it is nn/nn/nnnn or nn/nn/nn
var dRe = /^(\d{1,2})([\-\/])(\d{1,2})\2(\d{4}|\d{2})$/
if (!dRe.exec(dString)) {
return false;
}
// make sure it parses as date
// replace this part if you do not allow dashes
dString.replace(/-/g,"/");
var date = new Date(dString); // create a date object
if (!isNaN(date)) { // it may give NaN - if not test the parts
var parts = dString.split("/"); // split on slash
var dd = parseInt(parts[1],10); // day number
var mm = parseInt(parts[0],10)-1; // month - JS months start at 0
var yyyy = parseInt(parts[2],10); // year
// return true if all parts match
return dd===date.getDate() && mm === date.getMonth() && yyyy===date.getFullYear();
}
// here the date was not parsed as a date
return false;
}
window.onload=function() {
document.getElementById("output").innerHTML+="<br/>12/33/2012: "+isValidDateCheck('12/33/2012');
document.getElementById("output").innerHTML+="<br/>12/12/2012: "+isValidDateCheck('12/12/2012') ;
document.getElementById("output").innerHTML+="<br/>02/29/2012: "+isValidDateCheck('02/29/2012') ;
document.getElementById("output").innerHTML+="<br/>02/29/2013: "+isValidDateCheck('02/29/2013') ;
document.getElementById("output").innerHTML+="<br/>01/01/2013A: "+isValidDateCheck('01/01/2013A') ;
}
Thanks to #mplungjan. I have upvoted that answer.
#mplungjan approach (first suggested) is listed in http://jsfiddle.net/Lijo/uzSU6/7/. This was failed in IE8 for one scenario - http://jsfiddle.net/Lijo/uzSU6/12/.
So I have used a slightly different approach after referring How to validate a date?. See it here http://jsfiddle.net/Lijo/uzSU6/20/
EDIT
Please refer http://jsfiddle.net/uzSU6/37/ for scenarios that handle blank spaces
Feel free to give your suggestions/ challenges with this approach.
References
Check whether white spaces exist without using trim
Which equals operator (== vs ===) should be used in JavaScript comparisons?
How to validate a date?
CODE
function isValidDate(s)
{
var bits = s.split('/');
if(s.indexOf(' ') != -1)
{
//White space exists in the original date string
return false;
}
//Javascript month starts at zero
var d = new Date(bits[2], bits[0] - 1, bits[1]);
if ( isNaN( Number(bits[2]) ) )
{
//Year is not valid number
return false;
}
if ( Number(bits[2]) < 1 )
{
//Year should be greater than zero
return false;
}
//1. Check whether the year is a Number
//2. Check whether the date parts are eqaul to original date components
//3. Check whether d is valid
return d && ( (d.getMonth() + 1) == bits[0]) && (d.getDate() == Number(bits[1]) );
}
Related
I was referring this link and as I do not have 50 reputation I am not allowed to comment in the answer so posting this question. I did not get the statement where you can see a month is subtracted from months. This can be simple one but could anyone please clarify on this?
var m = matches1 - 1; ?
function isValidDate(date)
{
var matches = /^(\d{2})[-\/](\d{2})[-\/](\d{4})$/.exec(date);
if (matches == null) return false;
var d = matches[2];
var m = matches[1] - 1;
var y = matches[3];
var composedDate = new Date(y, m, d);
return composedDate.getDate() == d &&
composedDate.getMonth() == m &&
composedDate.getFullYear() == y;
}
var m = matches1 - 1; ?
months index starts from 0.
So while you think Jan is 1, it is actually 0 when you do date.getMonth().
Which is why when you get 1 from a date-string, you need to make it 0 before setting it to a date object.
In the spirt of the question, the validation function is way overdone. Only the month needs to be checked since if either the day or month is out of bounds, the month of the generated date will change.
Also the regular expression can be greatly simplified, consider (assuming the input is the peculiar US m/d/y format):
/* Validate a date string in US m/d/y format
** #param {string} s - string to parse
** separator can be any non–digit character (.-/ are common)
** leading zeros on values are optional
** #returns {boolean} true if string is a valid date, false otherwise
*/
function validateMDY(s) {
var b = s.split(/\D/);
var d = new Date(b[2],--b[0],b[1]);
return b[0] == d.getMonth();
}
var testData = ['2/29/2016', // Valid - leap year
'2/29/2015', // Invalid - day out of range
'13/4/2016', // Invalid - month out of range
'13/40/2016', // Invalid - month and day out of range
'02/02/2017']; // Valid
document.write(testData.map(function(a) {
return a + ': ' + validateMDY(a);
}).join('<br>'));
This may sound like a dumb question, but is it possible to have a 0 at the start of a number check, and have it work?
This is what I have:
function checkCosts() {
var date = document.getElementsByName("date")[0].value;
var roomtype = document.getElementsByName("roomtype")[0].value;
var night = document.getElementsByName("night")[0].value;
var month = date.substring(0, 2);
var year = date.substring(8, 10);
var day = date.substring(4, 6);
var time = month.concat(year);
var fulldate = day.concat(time);
if (time >= 0415 && <= 0915) {
if (roomtype == "Classic") {
if (night == "3") {
document.getElementById("cost").innerHTML = "1,480";
}
}
}
}
However, when I run it in jslint.com I get the following errors:
Unexpected '4' after '0'.
if(time >= 0415 && <= 0915){
line 9 column 28Unexpected trailing space.
if(time >= 0415 && <= 0915){
What's there is just one of a few different statements, all the variables will be used.
It would be possible to convert the strings into ints, but I don't know how to do this/if it will work.
A leading 0 is not the way to use ints. You should take a look here.
Otherwise just use the alpabetical order using a string comparison.
There is just no need to add zeros in front of the number. If the first number identifies the level of the room just add it, where you need it.
Instead of concatenating month with year, Concatenate year with month, And then check.
You need to do some modification in your logic.
function checkCosts() {
var date = document.getElementsByName("date")[0].value;
var roomtype = document.getElementsByName("roomtype")[0].value;
var night = document.getElementsByName("night")[0].value;
var month = date.substring(0, 2);
var year = date.substring(8, 10);
var day = date.substring(4, 6);
var time = year.concat(month);//Concat year with month.
var fulldate = day.concat(time);
if (time >= 1504 && <= 1509) { //Year should be first
if (roomtype == "Classic") {
if (night == "3") {
document.getElementById("cost").innerHTML = "1,480";
}
}
}
}
If you are trying to convert date to number and want to compare, use year first then month.
from this:
var time = month.concat(year);
I deduce "time" is a string.
then you should put quotes on 0415
strings are compared using alphabetical order (I hope you don't need globalization in this comparison) :
"04".concat("16") >= "0415"
-> true
"04".concat("14") >= "0415"
-> false
This question already has answers here:
javascript to find leap year
(15 answers)
Closed 4 years ago.
function leapYear(year){
var result;
year = parseInt(document.getElementById("isYear").value);
if (years/400){
result = true
}
else if(years/100){
result = false
}
else if(years/4){
result= true
}
else{
result= false
}
return result
}
This is what I have so far (the entry is on a from thus stored in "isYear"), I basically followed this here, so using what I already have, how can I check if the entry is a leap year based on these conditions(note I may have done it wrong when implementing the pseudocode, please correct me if I have)
Edit: Note this needs to use an integer not a date function
function leapYear(year)
{
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
The function checks if February has 29 days. If it does, then we have a leap year.
ES5
function isLeap(year) {
return new Date(year, 1, 29).getDate() === 29;
}
ES6
const isLeap = year => new Date(year, 1, 29).getDate() === 29;
Result
isLeap(1004) // true
isLeap(1001) // false
A faster solution is provided by Kevin P. Rice here:https://stackoverflow.com/a/11595914/5535820
So here's the code:
function leapYear(year)
{
return (year & 3) == 0 && ((year % 25) != 0 || (year & 15) == 0);
}
If you're doing this in an Node.js app, you can use the leap-year package:
npm install --save leap-year
Then from your app, use the following code to verify whether the provided year or date object is a leap year:
var leapYear = require('leap-year');
leapYear(2014);
//=> false
leapYear(2016);
//=> true
Using a library like this has the advantage that you don't have to deal with the dirty details of getting all of the special cases right, since the library takes care of that.
You can use the following code to check if it's a leap year:
ily = function(yr) {
return (yr % 400) ? ((yr % 100) ? ((yr % 4) ? false : true) : false) : true;
}
You can try using JavaScript's Date Object
new Date(year,month).getFullYear()%4==0
This will return true or false.
My Code Is Very Easy To Understand
var year = 2015;
var LeapYear = year % 4;
if (LeapYear==0) {
alert("This is Leap Year");
} else {
alert("This is not leap year");
}
I have a date string with the following format:
2012-09-20T01:36:51.556Z
Its a date field returned from mongodb as is. Chrome, FF, and IE are able to parse this string, however, Safari fails with an error Invalid Date. I have tried DateJS, but it fails to parse this date too. Any ideas how can I easily parse this date? Or, what particular thing is causing Safari to fail?
I am using the native node driver for mongodb. And it returns date as a string in the above-mentioned format.
My DateExtensions should parse that:
http://depressedpress.com/javascript-extensions/dp_dateextensions/
After adding the library to the page you'd parse the date with the static Date.parseIso8601(date) method.
The extensions are a bit heavy for just that (although you can pull out just the data parsing stuff if you like).
I'm suprised that Safari is having such issues as the date appears, to me, to be a perfectly valid ISO 8601 date (as defined here: http://www.w3.org/TR/NOTE-datetime). This is about as plain vanilla as a date gets. Total guess, but have you tried replacing the "T" seperator with a space? It's not standard but I've seen a lot of implementations that use it that way (and my component allows it).
For what it's worth, here's my method pulled from DP_DateExtensions - I think it'll do the trick for you:
// parseIso8601
// Attempts to convert ISO8601 input to a date
Date.parseIso8601 = function(CurDate) {
// Check the input parameters
if ( typeof CurDate != "string" || CurDate == "" ) {
return null;
};
// Set the fragment expressions
var S = "[\\-/:.]";
var Yr = "((?:1[6-9]|[2-9][0-9])[0-9]{2})";
var Mo = S + "((?:1[012])|(?:0[1-9])|[1-9])";
var Dy = S + "((?:3[01])|(?:[12][0-9])|(?:0[1-9])|[1-9])";
var Hr = "(2[0-4]|[01]?[0-9])";
var Mn = S + "([0-5]?[0-9])";
var Sd = "(?:" + S + "([0-5]?[0-9])(?:[.,]([0-9]+))?)?";
var TZ = "(?:(Z)|(?:([\+\-])(1[012]|[0]?[0-9])(?::?([0-5]?[0-9]))?))?";
// RegEx the input
// First check: Just date parts (month and day are optional)
// Second check: Full date plus time (seconds, milliseconds and TimeZone info are optional)
var TF;
if ( TF = new RegExp("^" + Yr + "(?:" + Mo + "(?:" + Dy + ")?)?" + "$").exec(CurDate) ) {} else if ( TF = new RegExp("^" + Yr + Mo + Dy + "[Tt ]" + Hr + Mn + Sd + TZ + "$").exec(CurDate) ) {};
// If the date couldn't be parsed, return null
if ( !TF ) { return null };
// Default the Time Fragments if they're not present
if ( !TF[2] ) { TF[2] = 1 } else { TF[2] = TF[2] - 1 };
if ( !TF[3] ) { TF[3] = 1 };
if ( !TF[4] ) { TF[4] = 0 };
if ( !TF[5] ) { TF[5] = 0 };
if ( !TF[6] ) { TF[6] = 0 };
if ( !TF[7] ) { TF[7] = 0 };
if ( !TF[8] ) { TF[8] = null };
if ( TF[9] != "-" && TF[9] != "+" ) { TF[9] = null };
if ( !TF[10] ) { TF[10] = 0 } else { TF[10] = TF[9] + TF[10] };
if ( !TF[11] ) { TF[11] = 0 } else { TF[11] = TF[9] + TF[11] };
// If there's no timezone info the data is local time
if ( !TF[8] && !TF[9] ) {
return new Date(TF[1], TF[2], TF[3], TF[4], TF[5], TF[6], TF[7]);
};
// If the UTC indicator is set the date is UTC
if ( TF[8] == "Z" ) {
return new Date(Date.UTC(TF[1], TF[2], TF[3], TF[4], TF[5], TF[6], TF[7]));
};
// If the date has a timezone offset
if ( TF[9] == "-" || TF[9] == "+" ) {
// Get current Timezone information
var CurTZ = new Date().getTimezoneOffset();
var CurTZh = TF[10] - ((CurTZ >= 0 ? "-" : "+") + Math.floor(Math.abs(CurTZ) / 60))
var CurTZm = TF[11] - ((CurTZ >= 0 ? "-" : "+") + (Math.abs(CurTZ) % 60))
// Return the date
return new Date(TF[1], TF[2], TF[3], TF[4] - CurTZh, TF[5] - CurTZm, TF[6], TF[7]);
};
// If we've reached here we couldn't deal with the input, return null
return null;
};
I'm sure you could create a much smaller, more streamlined version (my code is written more for maintainability than compactness) - but this will manage most variations of ISO8601 date times and has never let me down. ;^)
Hope this helps!
I ended up converting the date to a TimeStamp on the server side, before sending it to client. NodeJS (which is of course, based on Chrome's JavaScript engine) parses this format just fine.
I had the same issue and this worked for me: https://github.com/csnover/js-iso8601
It overrides the Date.parse function.
I am using MaskedEditExtender for entering a datetime. I am unable to figure out how to validate it.
Is there any Regular Expression for validating dates along with time MM/dd/yyyy hh:mm
or any Javascript function ??
THis will solve your issue:
^(([0]?[1-9]|1[0-2])/([0-2]?[0-9]|3[0-1])/[1-2]\d{3}) (20|21|22|23|[0-1]?\d{1}):([0-5]?\d{1})$
Javascript has Date.parse
it takes US formatted date of mm/dd/yyyy hh:mm:ss and with that format it works in all browsers I have tested: Firefox, Safari, Chrome, Edge
console.log(new Date(Date.parse("03/25/2022 12:00")))
will return 10th September 2011 at noon
Use DateTime.Parse or DateTime.TryParse (there are also ParseExact and TryParseExact equivalents).
If the string does not represent a valid DateTime it will not parse.
DateTime myDateTime = DateTime.ParseExact(myString,
"MM/dd/yyyy hh:mm",
CultureInfo.InvariantCulture);
The above will throw an exception if the value is not parseable. Use the Try variant if you want to avoid the chance of the exception being thrown - this requires an out parameter and testing the return value of the function for success.
And just in case you want the regular expression, this should work:
^(0[1-9]|1[012])/(0[1-9]|[12][0-9]|3[01])/(19|20)\d\d ([01]\d|2[0-3]):[0-5]\d$
The following Regex:
^([1-9]|([012][0-9])|(3[01]))\/([0]{0,1}[1-9]|1[012])\/([1-2][0-9][0-9][0-9]) [0-2][0-9]:[0-9][0-9]
gives this result:
03/03/2021 02:12
You may try following Function that Validates date in "dd/MM/yyyy HH:mm" format
function ValidateDate(dt) {
try {
var isValidDate = false;
var arr1 = dt.split('/');
var year=0;var month=0;var day=0;var hour=0;var minute=0;var sec=0;
if(arr1.length == 3)
{
var arr2 = arr1[2].split(' ');
if(arr2.length == 2)
{
var arr3 = arr2[1].split(':');
try{
year = parseInt(arr2[0],10);
month = parseInt(arr1[1],10);
day = parseInt(arr1[0],10);
hour = parseInt(arr3[0],10);
minute = parseInt(arr3[1],10);
//sec = parseInt(arr3[0],10);
sec = 0;
var isValidTime=false;
if(hour >=0 && hour <=23 && minute >=0 && minute<=59 && sec >=0 && sec<=59)
isValidTime=true;
else if(hour ==24 && minute ==0 && sec==0)
isValidTime=true;
if(isValidTime)
{
var isLeapYear = false;
if(year % 4 == 0)
isLeapYear = true;
if((month==4 || month==6|| month==9|| month==11) && (day>=0 && day <= 30))
isValidDate=true;
else if((month!=2) && (day>=0 && day <= 31))
isValidDate=true;
if(!isValidDate){
if(isLeapYear)
{
if(month==2 && (day>=0 && day <= 29))
isValidDate=true;
}
else
{
if(month==2 && (day>=0 && day <= 28))
isValidDate=true;
}
}
}
}
catch(er){isValidDate = false;}
}
}
return isValidDate;
}
catch (err) { alert('ValidateDate: ' + err); }
}