|
The comment says:
//Change the below values to determine which format of date you wish to check. It is set to dd/mm/yyyy by default.
... but the actual code defaults all indexes to 0:
var DayIndex = dayIdx !== undefined ? dayIdx : 0;
var MonthIndex = monthIdx !== undefined ? monthIdx : 0;
var YearIndex = yearIdx !== undefined ? yearIdx : 0;
------------------------------------
Calling isDate("1999-1-1", "-", 2, 1, 0) returns false.
My solution: I replaced
value = value.replace(/-/g, "/").replace(/\./g, "/");
var SplitValue = value.split(sepVal || "/");
... with
var SepVal = sepVal !== undefined ? sepVal : "/";
var SplitValue = value.split(SepVal);
|
|
|
|
|
Here is a another version which I removed the year validation that shall be between some years. I think that this check shall be done outside the function as its purpose shall be any date validation only. My opinion here. Though, the part I consider a real amelioration is the auto detection of indexes. This functionnality supports YYYY-mm-dd & dd-mm-YYYY. So, the usage of any other format shall then pass the parameters of indexes. The minimal year supported by this autodetection is 32. Though, another validation makes it impossible to go lower than year 1000.
function isDate(value, sepVal, dayIdx, monthIdx, yearIdx) {
try {
value = value.replace(/-/g, "/").replace(/\./g, "/");
sepVal = (sepVal === undefined ? "/" : sepVal.replace(/-/g, "/").replace(/\./g, "/"));
var SplitValue = value.split(sepVal);
if (SplitValue.length != 3) {
return false;
}
if (dayIdx === undefined || monthIdx === undefined || yearIdx === undefined) {
if (SplitValue[0] > 31) {
yearIdx = 0;
monthIdx = 1;
dayIdx = 2;
} else {
yearIdx = 2;
monthIdx = 1;
dayIdx = 0;
}
}
var DayIndex = dayIdx !== undefined ? dayIdx : 0;
var MonthIndex = monthIdx !== undefined ? monthIdx : 1;
var YearIndex = yearIdx !== undefined ? yearIdx : 2;
var OK = true;
if (!(SplitValue[DayIndex].length == 1 || SplitValue[DayIndex].length == 2)) {
OK = false;
}
if (OK && !(SplitValue[MonthIndex].length == 1 || SplitValue[MonthIndex].length == 2)) {
OK = false;
}
if (OK && SplitValue[YearIndex].length != 4) {
OK = false;
}
if (OK) {
var Day = parseInt(SplitValue[DayIndex], 10);
var Month = parseInt(SplitValue[MonthIndex], 10);
var Year = parseInt(SplitValue[YearIndex], 10);
var MonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (OK = (Month <= 12 && Month > 0)) {
var LeapYear = (Year & 3) == 0 && ((Year % 25) != 0 || (Year & 15) == 0);
MonthDays[1] = (LeapYear ? 29 : 28);
OK = Day > 0 && Day <= MonthDays[Month - 1];
}
}
return OK;
}
catch (e) {
return false;
}
}
modified 5-Mar-13 14:54pm.
|
|
|
|
|
Hello,
I am tring to use your code like this:
date = "30.12.1990";
alert(isDate(date,"."));
But the functions returns false, why is that so??
joni8a
|
|
|
|
|
You were right. I did some modifications, but did not try all the possibilities... So hyphens and dots were not valid separators... Now they are !
|
|
|
|
|
I modified the code a little bit to optimize it. Though, even with a one million loop, it doesn't make much difference.
|
|
|
|
|
How about this?
var isDateValid=function(b,c,d){var a=new Date(b,c-1,d);return a.getDate()==d&&a.getMonth()==c-1&&a.getFullYear()==b};
b = year
c = month
d = day
|
|
|
|
|
Another way to parse a string which has a leading '0' you can use the following code:
var test = '08';
var numberTest = (+test);
console.log(numberTest);
And thanks for the code, I also tried something like this 
|
|
|
|
|
function isDate(value, sepVal, monIdx, dayIdx, yearIdx) {
try {
var DayIndex = dayIdx;
var MonthIndex = monIdx;
var YearIndex = yearIdx;
value = value.replace(/-/g, "/").replace(/\./g, "/");
var SplitValue = value.split(sepVal);
Where the the following would hold true for the original posting:
sepVal = "/"
dayIdx = 0
monIdx = 1
yearIdx = 2
If you wanted to validate a date in a format of "YYYY-mm-dd" the following would be the values to be passed in:
sepVal = "-"
dayIdx = 2
monIdx = 1
yearIdx = 0
Thanks for the FANTASTIC start Ed!!!!
|
|
|
|
|
Hi,
I like the idea of the sepVal specifier - I might add that in when I get some spare time. Not so sure about the extra parameters - too much risk for inconsistency within an application I fear. However, I could make them optional parameters which would work quite nicely - I will look into doing that too, at some point
Thanks for your feedback - glad you found the code useful!
Ed
|
|
|
|
|
I am ALWAYS learning. As such, would it be possible to expand on the inconsistency issue you see, please ? Thanks!!!
|
|
|
|
|
Yeah sure I can
So when developing a small web application it is very easy to copy/paste code from one place to another and just make sure later that you change all the copies if you ever want to change something. This is made much easier by the fact that there is probably only a development team of < 5 people. However, inconsistency issues can arise if this technique is used when scaling up. For instance, if you take on a new member of staff, say someone from Europe for example. Now all of your code may be programmed using the traditionally British style of dd/mm/yyyy but your new European employee may use mm.dd.yyyy. If you set that new employee on a programming task and they forget (as they likely will) that the British standard should be used, you have immediately built in an inconsistency into your web application (which clearly is bad from a UI point of view and for data checking/verification). Furthermore, if the code is then copied around the place, a larger development team will rapidly lose track of where all the copies of the date checking code calls are and thus if you change to a different date format you can't guarantee you have changed all your code! A final problem is that say you wanted to run two versions of your site, one for Europe one for UK. Naturally you want to make as few changes as possible or even run the site as one website with automatic detection of where a request is coming from. If you have copied calls to isDate all over the place specifying different date formats for each call you will have yourself an all mighty mess trying to convert it for the new site.
So why is having one call with few parameters, and have defaults built in to the isDate function, better?
- If you change format, you change the code in one place and have site-wide results in seconds.
- If you want to build in request location detection, you can do it simply in the isDate function - one change, one place, very easy.
- If a developer new to the code needs to change something in the date validation, they only need to change it in one place and do not need to check every call to isDate to check that nothing is broken/unexpected or worse still, needs redoing.
So clearly in bigger applications it becomes more sensible to copy as little as possible and have it all in one place. If you did want to separate out the date format from the date validation, it should be done by creating a new method/JS file to contain one set of code for doing the format checking and that new code should be called from one place (in the isDate cycle) - from within isDate, not by methods calling isDate else you'd be back to the problem of duplicated code
Hope explains things well enough,
Ed
|
|
|
|
|
When I said "When I get some spare time", I probably should have said "In 5 minutes"
Ed
|
|
|
|
|
You forgot to check if the Day is greater than zero.
Should be something like this:
OK = Day > 0 && (LeapYear ? Day <= 29 : Day <= 28);
Apart from that, very good code.
|
|
|
|
|
I'm surprised neither I nor anybody else spotted this sooner! I have updated the code to fix this.
Thanks and glad the code helped,
Ed
|
|
|
|
|
The line reading:
if (OK = ((Year > 1900) && (Year < new Date().getFullYear()))) {
is not a good idea. First off, it causes dates from the current year to be judged to be invalid. I think you meant <= rather than <.
Second, this line makes the assumption that a year less than 1900 is invalid. There's no reason for a general-purpose function such as this one to assume something like that. 1899 is a perfectly valid date.
A better design for this line, and the one I'm now using, is:
if (OK = ((Year >= 1000) && (Year <= 9999))) {
This way it simply insures that the year is a four-digit number, which is, I think, what this function should do.
|
|
|
|
|
Well to start with if you read the messages below titled "Year Validation" you would see that this "issue" has already been covered. I did not mean <= , I meant < . No matter what I put in the code it will never satisfy everyone, as this is one of the things where everyone has different needs depending upon application. The code is readable/good enough that you found how to change this piece of validation so it isn't much of a problem.
Secondly, I should probably have assumed the date shouldn't be less than 1970, given that a number of computer date systems don't handle dates less than 1970 so a "general-purpose function" would account for that. For example the minimum positive date for Java code is Jan 1 1970 (my code only allows positive dates) so if you were using a Java server, your code would not work.
Finally, to re-iterate what I said before, better design for you but not for me, or the other poster below or anyone else who needed something different to what you do. For example, in my application I wanted real birth dates and I was targeting younger people of similar age to myself, so a birth date of < 1900 was unrealistic.
Hope this answers your query,
Ed
|
|
|
|
|
The Script you wrote has a small bug.
This check if (OK = ((Year > 1900) && (Year < new Date().getFullYear())))
only checks <(less than) or >(greater than) value and hence returns false even when
it should not (eg 2012 < 2012 ).
Please take a note of it.
Rest all is fine.
Good Work.!
- Regards Xtrem -  Ω
|
|
|
|
|
Thank you for pointing this out to other users but what you call a bug, I call intended design Unusual, I know and probably worth other users noting, sorry if this caused you an issue. I tried to make the code readable enough so that things like this could be changed easily though. You could argue that blocking dates above the current year is a bug, could you not? I think you see where that though leads...
Best regards,
Ed
|
|
|
|
|
That'd be true if the date entered within the current year was actually larger than today's date Otherwise, nice script and thank you!
Greg
|
|
|
|
|
Very minor improvement (bug fix) with the replacing of dots or dashes as separators - replace in Javascript only replaces first occurrence of a string rather unless regex with global replace is used - this is now done so that it actually works as intended - i.e. it converts the following dates to the following result before processing:
Input : Processed Input
1/1/1 : 1/1/1
1.1.1 : 1/1/1
1-1-1 : 1/1/1
Surprised nobody noticed this before... Anyway best regards,
Ed
|
|
|
|
|
I am *very* surprised that none of our North American friends (who think a date goes mm/dd/yyyy) or Europeans who use separators other than '/' has complained that their format doesn't work.
|
|
|
|
|
Yes I guess that is a little surprising. But then again, I would hope it is fairly simple to adapt my code. Although I would like to point out that my code does allow for the separators '/', '.' and '-' so that should cover a lot of them. Furthermore, to simply switch the values around isn't hard...just change the indexes in the value array to what you want. I think I'll update have updated my code to make that easier - it's only a simple change!
|
|
|
|
|
Reason for my vote of 5
found to be complete, simple and elegant code.
|
|
|
|
|
I believe that the snippet
(Year < new Date().getFullYear())
should actually be
(Year <= new Date().getFullYear())
to allow this year to be chosen.
|
|
|
|
|
Thanks for that - at the moment there appears to be a bug when trying to modify/improve my tip/trick so I can't change the code. Really that line just depends on what you want to be the max year. I will add this variable in when I get the chance. For what I wanted, I didn't want to allow the current year.
Hope this explains,
Ed 
|
|
|
|
|