How to check invalid date in Javascript in FireFox - javascript

I want to test invalid date, the function I wrote works fine in chrome but not in Firefox. Here are some examples not working in FF:
new Date('01/99/2010') = return Valid Date
new Date('99/01/2010') = return Valid Date
var day='01', month = '99', year = '2010';
new Date(year,month,day) = return Valid Date
var day='99', month = '01', year = '2010';
new Date(year,month,day) = return Valid Date
Above methods return "Invalid Date" in Chrome, but not in Firefox. Does anyone know the proper way to validate date in Firefox.
PS: Input string could be - mm/dd/yyyy or dd/mm/yyyy or yyyy/mm/dd

It looks like Firefox takes this rule one step further than Chrome:
Note: Where Date is called as a constructor with more than one
argument, if values are greater than their logical range (e.g. 13 is
provided as the month value or 70 for the minute value), the adjacent
value will be adjusted. E.g. new Date(2013, 13, 1) is equivalent to
new Date(2014, 1, 1), both create a date for 2014-02-01 (note that the
month is 0-based). Similarly for other values: new Date(2013, 2, 1, 0,
70) is equivalent to new Date(2013, 2, 1, 1, 10) which both create a
date for 2013-03-01T01:10:00.
Source - MDN Date documentation.
The emphasis here is on with more than one argument. That's why Chrome does what Firefox does for:
new Date(2010, 99, 1); - a valid date object.
but because:
new Date('01/99/2010'); is technically only a single argument, it doesn't fall for the above rule in Chrome, but Firefox allows it through.
With the above in mind, and the inconsistency across browsers, it looks like you might be stuck writing a validator for the day, month and year separately from trying to do it via the Date object if you want it to work in Firefox.

You can use regex. Try this:
var rgx = /^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/;
console.log(rgx.test("99/12/2015"));
jsFiddle

I would use a internal JavaScript funtion for validating Dates, as browsers do handle those data types very differently.
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 checkDate = new Date(y, m, d);
return checkDate.getDate() == d &&
checkDate.getMonth() == m &&
checkDate.getFullYear() == y;
}
You would then use it like this:
var d = new Date(2010, 99, 1);
console.log( isValidDate(d) ); // returns false no valid date

Related

If current date and time is greater (after) than X

I am trying to create an if statement that can check today's date and time and if it's greater than a predefined date and time, do something. I'm looking to do this in vanilla JS only and get it to work in IE.
This is the basic working code for Chrome.
var ToDate = new Date()
if (new Date("2018-11-30 05:00").getTime() > ToDate.getTime()) {
alert("true")
} else {
alert("false")
}
How can I make something like this work in IE?
if (new Date("2018-11-30 05:00").getTime() > ToDate.getTime()) {
On firefox and chrome there are no issues with it. On Internet Explorer it's false.
On IE (or in general) the string needs to be an RFC2822 or ISO 8601 formatted date
Example:
new Date("2018-11-29T19:15:00.000Z")
If you need portable solution (eg. support older Internet Explorer) I would use this constructor instead:
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
Keep in mind that monthIndex starts from 0 (January).
Test:
function assertTrue(exp, message) {
if (exp === false) {
message = message || 'Assertion failed';
alert(message);
throw message;
}
}
function testShouldPassForDatesInTheFuture() {
var ToDate = new Date(2018, 10, 29);
assertTrue(new Date(2018, 10, 30).getTime() > ToDate.getTime());
}
function testShouldPassForDatesInThePast() {
var ToDate = new Date(2018, 10, 29);
assertTrue(new Date(2018, 10, 28).getTime() < ToDate.getTime());
}
testShouldPassForDatesInThePast();
testShouldPassForDatesInThePast();
alert('All test passed');
You need to append 'T00:00:00.000Z' to your date.
new Date("2018-11-30" + 'T00:00:00.000Z')
Full code is below:
var ToDate = new Date()
if (new Date("2018-11-30" + 'T00:00:00.000Z').getTime() > ToDate.getTime()) {
alert("true")
} else {
alert("false")
}
Your issue is that the date format YYYY-MM-DD HH:mm is not supported by ECMAScript, so parsing is implementation dependent. Safari, for example:
new Date("2018-11-30 05:00")
returns an invalid date.
You can first parse the string manually, either with a bespoke function (e.g. How to parse a string into a date object at JavaScript?) or a library, then you can compare the result with new Date() as for Compare two dates with JavaScript.
A simple parse function is not difficult:
/* Parse string in YYYY-MM-DD HH:mm:ss to a Date
* All parts after YYYY-MM are optional, milliseconds ignored
*/
function parseDate(s) {
var b = s.split(/\D/);
return new Date(b[0], b[1]-1, b[2]||1, b[3]||0, b[4]||0, b[5]||0);
}
["2018-11-23 17:23",
"2019-01",
"2020-12-31 23:59:59"].forEach(s => {
console.log(`${s} => ${parseDate(s).toString()}`);
});
Then you can compare dates using <, <=, > and >=.
In this case, a date like "2018-01-01" will be considered past at any time after 2018-01-01 00:00:00.000.
Alternatively, since the string is similar to ISO 8601 format, you can compare the parts of the string with a similarly formatted string for today:
// Return date string in YYYY-MM-DD HH:mm:ss format
// Only return as many parts as len, or all 6 if missing
function formatDate(d, len) {
var parts = [d.getFullYear(), '-'+d.getMonth()+1, '-'+d.getDate(), ' '+d.getHours(), ':'+d.getMinutes(), ':'+d.getSeconds()];
var spacer = ['-','-',' ',':',':'];
len = len || 6;
return parts.splice(0, len).join('');
}
['2018-06-30 12:04',
'2018-10',
'2018-12-15 03:14:45',
'2019-01-01',
'2020-12-15 03:14:45'].forEach(s => {
console.log(`${s} has passed? ${s < formatDate(new Date(), s.split(/\D/).length)}`);
});
In this case, 2018-01-01 will be equal to any date generated on that day, and "2018-01" will be equal to any date generated in January 2018. It's up to you whether you use < or <= for the comparison.
So you need to consider carefully where you draw the boundary between earlier and later and adjust the logic accordingly.

Date Validation - how to work around Javascript's auto-correcting of dates?

I want to validate dates by Javascript and found this nice answer:
https://stackoverflow.com/a/1353711/3391783
but when i try to use it to validate dates, it seems like Javascript is auto-correcting my date by taking the closest valid date. so this will return true even though 2014-11-31 is not a valid date (Javascript months start at 0, so 10 equals November):
function isValidDate(d) {
if ( Object.prototype.toString.call(d) !== "[object Date]" )
return false;
return !isNaN(d.getTime());
}
var test_date = new Date(2014, 10, 31);
console.log( test_date );
console.log( isValidDate(test_date) );
seems like creating the Date is automatically switching it to 2014-12-01 which is a correct date.
but I would like to be able to validate user input without changing it.
So how can i create an invalid new Date() in Javascript?
Or is there a much simpler way to do this?
You can use the auto-correction in the Date object to validate the date. Just check the input against what you have in the Date object:
var y = 2014, m = 10, d = 31;
var test_date = new Date(y, m, d);
var valid =
test_date.getFullYear() == y &&
test_date.getMonth() == m &&
test_date.getDate() == d;
document.write(valid);
When it comes to handling dates in JavaScript, I'm a big fan of Moment.js. As you can see here, they do a good job of validating dates: http://momentjs.com/docs/#/parsing/is-valid/
new Date(2013, 25, 14).toString(); // "Sat Feb 14 2015 00:00:00 GMT-0500 (EST)"
moment([2015, 25, 35]).format(); // 'Invalid date'
Here's a function I wrote a while back that demonstrates Guffa's solution.
function isValidDate(checkDate) {
if(!/\d\d\/\d\d\/\d\d\d\d/.test(checkDate)) {
return false; // checkDate is not formatted as ##/##/####
} else {
// split checkDate into three pieces
var strMM = checkDate.split('/')[0];
var strDD = checkDate.split('/')[1];
var strYYYY = checkDate.split('/')[2];
// create new Date() object from split pieces
var strDateCheck = new Date(strYYYY,(strMM - 1),strDD);
// evaluate each piece of resulting date object against each corresponding piece of checkDate
if(((strDateCheck.getMonth() + 1) == strMM) && (strDateCheck.getDate() == strDD) && (strDateCheck.getFullYear() == strYYYY)) {
/* if you wish, add additional validation constraints here */
return true; // all three pieces match exactly
} else {
return false; // at least one piece did not match
}
}
}

javascript - compare dates in different formats

I have 2 dates which I need to compare to see if one is greater than the other but they are in different formats and I'm not sure of the best way to compare the 2.
The formats are:
1381308375118 (this is var futureDate)
which is created by
var today = new Date(); today.setHours(0, 0, 0, 0); var futureDate = new Date().setDate(today.getDate() + 56); //56 days in the future...
And the other format is
2013/08/26
Any ideas how I can compare the 2?
Without using a 3rd party library, you can create new Date objects using both those formats, retrieve the number of milliseconds (since midnight Jan 1, 1970) using getTime() and then simply use >:
new Date("2013/08/26").getTime() > new Date(1381308375118).getTime()
I strongly recommend using datejs library.
Thus this can be written in one single line:
Date.today().isAfter(Date.parse('2013/08/26'))
I would make sure that I am comparing the "date" element of each format and exclude any "time" element. Then with both dates converted to milliseconds, simply compare the values. You could do something like this. If dates are equal it returns 0, if the first date is less that the second then return -1, otherwise return 1.
Javascript
function compareDates(milliSeconds, dateString) {
var year,
month,
day,
tempDate1,
tempDate2,
parts;
tempDate1 = new Date(milliSeconds);
year = tempDate1.getFullYear();
month = tempDate1.getDate();
day = tempDate1.getDay();
tempDate1 = new Date(year, month, day).getTime();
parts = dateString.split("/");
tempDate2 = new Date(parts[0], parts[1] - 1, parts[2]).getTime();
if (tempDate1 === tempDate2) {
return 0;
}
if (tempDate1 < tempDate2) {
return -1;
}
return 1;
}
var format1 = 1381308375118,
format2 = "2013/08/26";
console.log(compareDates(format1, format2));
On jsfiddle
Maybe you can use Date.parse("2013/08/26") and compare with former one
Follow these steps to compare dates
Each of your date must to passed through Date object i.e. new Date(yourDate).
Now dates will have same format and these will be comparable
let date1 = new Date()
let date2 = "Jan 1, 2019"
console.log(`Date 1: ${date1}`)
console.log(`Date 2: ${date2}`)
let first_date = new Date(date1)
let second_date = new Date(date2)
// pass each of the date to 'new Date(yourDate)'
// and get the similar format dates
console.log(`first Date: ${first_date}`)
console.log(`second Date: ${second_date}`)
// now these dates are comparable
if(first_date > second_date) {
console.log(`${date2} has been passed`)
}

Javascript date format using string month

All the other topics on date format assume that dates are entered as integers.
I'm writing a script (Linux) that requires the month to be a string (Jan, Feb, Mar etc) and need to validate the dates.
I've written a clunky routine that extracts the month, determines the month number and then does the comparison but I was hoping there might be something neater out there to do this? I thought I had seen something about using a 'format' method but I can't find it now...
I've tried this but it fails miserably:
var checkDate1 = document.getElementById('fromDate').value;
var checkDate2 = document.getElementById('toDate').value;
tmpDate1 = new Date(checkDate1);
tmpDate2 = new Date(checkDate2);
if (tmpDate1 < tmpDate2) {
where a typical field entry will be '12-may-2012', for example.
NOTE: I don't have access to add any fancy, whizzy libraries to the system so have to make do with the vanilla stuff.
In JavaScript, to be parsed in the constructor, string Date must have the format : D, d M Y H:i:s
Now it'll be : Tue, 29 May 2012 15:22:59
If you want to stay with string, you'll have to make a fancy function that parse your value, and find what day will be the 29 May of 2012.
Another method ( and easier ) is to create a new Date, parse you value and use the on of the other constructors
var today = '05-29-2012',
aToday = today.split('-'),
dToday = new Date(aToday[2], aToday[0], aToday[1], 0, 0, 0, 0),
tomorrow = '05-30-2012',
aTomorrow = tomorrow.split('-'),
dTomorrow = new Date(aTomorrow[2], aTomorrow[0], aTomorrow[1], 0, 0, 0, 0);
if (dTomorrow.getTime() > dToday.getTime() ) {
console.log('Tomorrow is tomorrow');
} else {
console.log('Tomorrow is not tomorrow');
}

Timestamp parse not working in IE

I have a timestamp in the following format:
[yyyy-MM-ddThh:mm:ssZ] (example: 2015-05-15T03:34:17Z)
I want's to parse this timestamp into Date and format is like: [Fri May 15 2015 09:04:17 GMT +5:30]:
Now, i am use the following code to parse and it work's fine in Firefox 3.6+ browsers. But the problem is, it's not working in internet explorer (IE) 8, in IE it returns 'NaN'.
My Javascript code is:
var myDate = new Date(timestampDate);
//In Firefox i get myDate as Date object and i can get day, month and year. But in IE this myDate value is coming as NaN
var day = myDate.getDate();
var month = myDate.getMonth();
var year = myDate.getFullYear();
Any help is rewarded. Please give me a solution to make this working in IE also.
(function(){
//if the browser correctly parses the test string, use its native method.
var D= new Date('2011-06-02T09:34:29+02:00');
if(D && +D=== 1307000069000) Date.fromISO= function(s){
return new Date(s);
};
Date.fromISO= function(s){
var day, tz,
rx=/^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
p= rx.exec(s) || [];
if(p[1]){
//extract the y-m-d h:m:s.ms digits:
day= p[1].split(/\D/);
for(var i= 0, L= day.length; i<L; i++){
day[i]= parseInt(day[i], 10) || 0;
};
day[1]-= 1; //adjust month
//create the GMT date:
day= new Date(Date.UTC.apply(Date, day));
if(!day.getDate()) return NaN;
if(p[5]){
// adjust for the timezone, if any:
tz= (parseInt(p[5], 10)*60);
if(p[6]) tz+= parseInt(p[6], 10);
if(p[4]== '+') tz*= -1;
if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
}
return day;
}
return NaN;
}
})();
//test alert(Date.fromISO("2015-05-15T03:34:17Z").toUTCString())
yyyy-MM-ddThh:mm:ssZ is an ISO date. Browsers don't support them very well, FireFox doesn't parse 2015-05-15T03:34:17+01 for example.
You'll have to extract the elements out of the string manually before creating your date.
I had the same problem and found this, supposing that you use jQuery UI:
$.datepicker.parseDate('yy-mm-dd', '2014-02-14');
This is a useful method of the UI Datepicker. I'm just about to write my own date parser to make my code jqui-independent but it may help others so I leave this answer here.

Categories

Resources