I've inherited the following script and it needs to be improved upon some. The function checks that only allowed characters are entered (0123456789/) and then formats a date entered as 1/1/12 will be reformatted as 01/01/2012. This part works just fine after a little tweaking. I now need to take the validation a step further and add the year if it is omitted meaning if a user enters 1/1, it needs to be formatted and have the current year added (e.g. 01/01/2012).
Example of user inputs and required (working) outputs
a/a/a alert user of error - check
1/2/10 updates input field to read as 01/03/2010
01/01/12 updates input field to read as 01/01/2012
1/10/2 updates input field to read as 01/10/2002
Desired Update (in addition to above)
1/9 updates input field to read as 01/09/2012
Here is the current function (you are welcome to change, rewrite, whatever, as long as the above functionality is retained). jQuery 1.7 library is in use and can be implemented.
function ValidateDate(obj)
{
/************************************************
DESCRIPTION: Validates that a string contains only
valid dates with 2 digit month, 2 digit day,
4 digit year. Date separator has to be /
Uses combination of regular expressions and
string parsing to validate date.
Ex. mm/dd/yyyy
PARAMETERS:
ValidateDate(strValue) - String to be tested for validity
RETURNS:
True if valid, otherwise false.
REMARKS:
Avoids some of the limitations of the Date.parse()
method such as the date separator character.
*************************************************/
var checkOK = "0123456789/";
var checkStr = obj.value;
var allValid = true;
var p = /(\d{1,2})\/(\d{1,2})\/(\d{1,4})/;
var objRegExp = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/;
// check to see if valid characters were used
for (i = 0; i < checkStr.length; i++)
{
ch = checkStr.charAt(i);
for (j = 0; j < checkOK.length; j++)
if (ch == checkOK.charAt(j))
break;
if (j == checkOK.length)
{
allValid = false;
break;
}
}
if (!allValid)
{
alert("Please use only a combination of " + checkOK + "\'s charaters in the date field. Dates should be entered in the format of mm/dd/yyyy.");
setTimeout((function() { obj.select() }), 0);
return (false);
}
// converts to mm/dd/yyyy format
if (!obj.value.match(p)) return;
num=new Array();
num=obj.value.match(p);
if (num[1].length == 1) num[1]="0" + num[1];
if (num[2].length == 1) num[2]="0" + num[2];
if (num[3].length == 1) num[3]="200" + num[3];
if (num[3].length == 2) num[3]="20" + num[3];
obj.value= num[1] + "/" + num[2] + "/" + num[3];
//check to see if in correct format
if(!objRegExp.test(obj.value))
{
alert('The date entered is not properly formatted.');
return false; //doesn't match pattern, bad date
}
else{
var arrayDate = obj.value.split(RegExp.$1); //split date into month, day, year
var intDay = parseInt(arrayDate[1],10);
var intYear = parseInt(arrayDate[2],10);
var intMonth = parseInt(arrayDate[0],10);
//check for valid month
if(intMonth > 12 || intMonth < 1) {
alert('The date entered is invalid');
return false;
}
//create a lookup for months not equal to Feb.
var arrayLookup = { '01' : 31,'03' : 31, '04' : 30,'05' : 31,'06' : 30,'07' : 31,
'08' : 31,'09' : 30,'10' : 31,'11' : 30,'12' : 31}
//check if month value and day value agree
if(arrayLookup[arrayDate[0]] != null) {
if(intDay <= arrayLookup[arrayDate[0]] && intDay != 0)
return true; //found in lookup table, good date
}
//check for February
var booLeapYear = (intYear % 4 == 0 && (intYear % 100 != 0 || intYear % 400 == 0));
if( ((booLeapYear && intDay <= 29) || (!booLeapYear && intDay <=28)) && intDay !=0)
return true; //Feb. had valid number of days
}
alert(obj.value + ' is not a valid date.');
// return false; //any other values, bad date
}
Some points to object:
You don't have to check for valid characters, because your match regexp already needs them. If you really want to, use /^[\d\/]*$/.test() instead of that loop.
To match dates like 1/1, use /\d{1,2}\/\d{1,2}(\/\d{1,4})?/ as p and just do a num = obj.value.split("/") instead of matching groups
To validate the date, have a look at javascript date validation using date object
You should also allow ISO date format YYYY-MM-DD, which is parsed natively by Date()
Related
I have a input field for a phonenumber.
Now i want to check with jquery/javascript the syntax and the characters of the number
I only accept this format: 31-123456789 (also more groupes seperated by - will be ok)
Its important to check if there is the international code at first.
I think about to do a kind of replace for replace "()/.:;" characters and check if the first letter is a 0.
But this looks for large code, also there is not check if the user has enter disallowed characters for example Abc...
How i can check and format the following examples in the easiest way?
031(123)123 -> should return 31-123-123
(0123)123 -> should return a error (no international code)
031.123 -> should return a error (no international code)
31.(123)123 -> 31-123-123
+31.123.123 -> 31-123-123
+31 (123) 123 -> 31-123-123
etc.
Thanks for showing and explaing me the way to do it.
Here is a try, that you could build on. It also fill all your requirement.
Now you can simply add your configration to internationalCodes and the method will do its job
// All valid internationl code
var internationalCodes= [
{ codes:["031", "0031", "31"], translateTo: "31", minLength: 8 }
]
var seperatorCount =3;
var seperator = "-";
function getNumber(num){
var notValid = num + " not valid";
num = num.trim().replace(/[^0-9]/g, ""); // replace all none number char
// find the international configration settings
var r = internationalCodes.filter(x=>
x.codes.findIndex(i=> num.substr(0, i.length)== i) != -1)
if (r.length<=0) // no internationalCodes configration
return notValid;
r = r[0];
if (num.length<r.minLength)
return notValid;
var resultNum = r.translateTo;
var code = r.codes.filter(x=> num.substr(0, x.length) == x)[0]
num = num.substr(code.length, num.lengt)
for (var i = 0; i< num.length; i++)
{
if (i % seperatorCount == 0)
resultNum += seperator;
resultNum += num[i];
}
return resultNum;
}
console.log(getNumber("031(123)123"))
console.log(getNumber("(0123)123"))
console.log(getNumber("031.123"))
console.log(getNumber("31.(123)123"))
console.log(getNumber("+31.123.123"))
console.log(getNumber("+31 (123) 123"))
console.log(getNumber("+50 (123) 123"))
I have this string:
002 2.0 (100aa) 95-97
I then want regex the 95-97 portion of it and paste it with relevant two numbers so I get a year.
In example, 96-97 should become 1995-1997, but 00-05 should become 2000-2005 (all numbers between 0 and 16 should be pasted with 20, but all other numbers with 19).
Then, when I have i.e. 1995-1997 I want to check if a year (i.e. 1996) is present inside 1995-1997 interval or not, and return a bolean.
How would one wright such code?
Best Regards
You could use the callback variant of replace:
function parseString(str) {
function padYear(year) {
return year < 30 ? 2000+year :
year < 100 ? 1900+year : year;
}
var result = {};
result.hasCurrentYear = false;
result.str = str.replace(/(\d\d)-(\d\d)$/g, function (match, yr1, yr2) {
yr1 = padYear(+yr1);
yr2 = padYear(+yr2);
var yrNow = (new Date).getFullYear();
result.hasCurrentYear = yrNow >= yr1 && yrNow <= yr2;
return yr1 + '-' + yr2;
});
return result;
}
var str = '002 2.0 (100aa) 95-16';
console.log(parseString(str));
Note that I made the split at year 30, as the solution will become outdated soon if you use 16 as split year.
I suppose there's a much simpler way to check if a certain year is in "range".The solution using String.split, Array.map functions and Number constructor:
var str = "002 2.0 (100aa) 95-97";
function checkYearInRange(str, year) {
year = Number(year);
var range = str.split(" ").pop().split('-').map((v) => Number((Number(v) > 16)? "19"+v : "20"+v));
return (range[0] <= year && year <= range[1]);
}
console.log(checkYearInRange(str, "1996")); // true
console.log(checkYearInRange(str, "2015")); // false
I'm using date.js to apply conditional formatting to a data grid. The data is parsed from a javascript array. All of my conditions are working correctly, except for this one:
if (val < today && val > '01-01-2000')
val is a string in MM-dd-yyyy format that I can't change. So I used date.js to convert today's date to a string in MM-dd-yyyy format and make the comparison. The problem is that 01-17-2014 is seen as less than 04-08-2013 - since it is comparing strings.
What's the best way around this?
I'd like to make it simple, which is why I converted to strings in the first place, but I'm not sure how to get around the year issue.
Thanks for any help!
var today = new Date.today().toString("MM-dd-yyyy");
var tomorrow = new Date.today().addDays(1).toString("MM-dd-yyyy");
var upcoming = new Date.today().addDays(7).toString("MM-dd-yyyy");
function eXcell_edncl(cell) {
this.base = eXcell_edn;
this.base(cell);
this.setValue = function(val) {
if (val.indexOf('ACT') >= 0) this.cell.style.backgroundColor="lightgreen";
else if (val.indexOf('PV') >= 0) this.cell.style.backgroundColor="lightgreen", this.cell.style.fontSize="20px";
else if (val.indexOf('YES') >= 0) this.cell.style.backgroundColor="lightgreen", this.cell.style.fontSize="20px";
else if (val < today && val > '01-01-2000') this.cell.style.backgroundColor="red";
else if (val == today) this.cell.style.backgroundColor="orange";
else if (val == tomorrow) this.cell.style.backgroundColor="yellow";
else if (val > tomorrow && val <= upcoming) this.cell.style.backgroundColor="lightyellow";
else this.cell.style.backgroundColor="";
this.cell.innerHTML = this.grid._aplNF(val, this.cell._cellIndex);
}
}
The best way around this issue is to not convert your Date objects into Strings. "01-17-2014" < "04-08-2013"evaluates to true because "01" < "04" is true, so whatever is tacked onto those strings will always evaluate the same way. However, using the less than/greater than operators on Date objects will behave as expected. So you can modify your existing if statement to be
if (new Date(val) < new Date(today) && new Date(val) > new Date('01-01-2000'))
and that will resolve your problem, but you are probably better off using the Date objects to begin with.
Since you are using date.js you can use its compare function, as described on the documentation:
Date.compare ( Date date1, Date date2 ) : Number
Compares the first date to the second date and returns an number indication of their relative values. -1 = this is lessthan date. 0 = values are equal. 1 = this is greaterthan date.
See the documentation for a code example.
You may not be able to change the format of the date string in the UI, but it should not matter what format it is in in the back-end. You should change the code to use ISO 8601 which was designed to allow easy comparison in string format (among other advantages).
The format of your dates would then be yyyy-MM-dd which would allow you to compare them as strings.
And because it is relevant, check out this XKCD comic if you are still on the fence.
Ended up with the following working. Needed to parse the values coming in:
var today = new Date.today().toString("MM-dd-yyyy");
var today2 = new Date.today();
var old = new Date(2000, 0, 1);
var tomorrow = new Date.today().addDays(1).toString("MM-dd-yyyy");
var upcoming = new Date.today().addDays(7).toString("MM-dd-yyyy");
function eXcell_edncl(cell) {
this.base = eXcell_edn;
this.base(cell);
this.setValue = function(val) {
var val2 = new Date.parse(val);
if (val.indexOf('ACT') >= 0) this.cell.style.backgroundColor="lightgreen";
else if (val.indexOf('PV') >= 0) this.cell.style.backgroundColor="lightgreen", this.cell.style.fontSize="20px";
else if (val.indexOf('YES') >= 0) this.cell.style.backgroundColor="lightgreen", this.cell.style.fontSize="20px";
else if (val2 < today2 && val2 > old) this.cell.style.backgroundColor="red";
else if (val == today) this.cell.style.backgroundColor="orange";
else if (val == tomorrow) this.cell.style.backgroundColor="yellow";
else if (val > tomorrow && val <= upcoming) this.cell.style.backgroundColor="lightyellow";
else this.cell.style.backgroundColor="";
this.cell.innerHTML = this.grid._aplNF(val, this.cell._cellIndex);
}
}
I've researched this but none of the code I use seems to work. South African ID numbers contain date of birth and gender. All I want is it to pull in that information and verify it when their ID number is entered into an input field, preferably in jQuery or javascript
Any help is appreciated,
Dawid
You could use Koenyn's regex validation, not so sure how a single-digit number (0-9?) from the input represents the gender but basing on this tool you provided and David Russell's Using Javascript to validate South African ID Numbers, here's an untested attempt:
UPDATE 1:
After following this thread, What is a South African ID number made up of?, I updated my implementation to include the gender and citizenship tests.
UPDATE 2:
Forgot to wrap the month number increment id_month + 1 within the date string fullDate, updating solution with Dawid's fix.
HTML Markup:
<div id="error"></div>
<form id="idCheck">
<p>Enter the ID Number: <input id="idnumber" /> </p>
<p> <input type="submit" value="Check" /> </p>
</form>
<div id="result"> </div>
Javascript:
function Validate() {
// first clear any left over error messages
$('#error p').remove();
// store the error div, to save typing
var error = $('#error');
var idNumber = $('#idnumber').val();
// assume everything is correct and if it later turns out not to be, just set this to false
var correct = true;
//Ref: http://www.sadev.co.za/content/what-south-african-id-number-made
// SA ID Number have to be 13 digits, so check the length
if (idNumber.length != 13 || !isNumber(idNumber)) {
error.append('<p>ID number does not appear to be authentic - input not a valid number</p>');
correct = false;
}
// get first 6 digits as a valid date
var tempDate = new Date(idNumber.substring(0, 2), idNumber.substring(2, 4) - 1, idNumber.substring(4, 6));
var id_date = tempDate.getDate();
var id_month = tempDate.getMonth();
var id_year = tempDate.getFullYear();
var fullDate = id_date + "-" + (id_month + 1) + "-" + id_year;
if (!((tempDate.getYear() == idNumber.substring(0, 2)) && (id_month == idNumber.substring(2, 4) - 1) && (id_date == idNumber.substring(4, 6)))) {
error.append('<p>ID number does not appear to be authentic - date part not valid</p>');
correct = false;
}
// get the gender
var genderCode = idNumber.substring(6, 10);
var gender = parseInt(genderCode) < 5000 ? "Female" : "Male";
// get country ID for citzenship
var citzenship = parseInt(idNumber.substring(10, 11)) == 0 ? "Yes" : "No";
// apply Luhn formula for check-digits
var tempTotal = 0;
var checkSum = 0;
var multiplier = 1;
for (var i = 0; i < 13; ++i) {
tempTotal = parseInt(idNumber.charAt(i)) * multiplier;
if (tempTotal > 9) {
tempTotal = parseInt(tempTotal.toString().charAt(0)) + parseInt(tempTotal.toString().charAt(1));
}
checkSum = checkSum + tempTotal;
multiplier = (multiplier % 2 == 0) ? 1 : 2;
}
if ((checkSum % 10) != 0) {
error.append('<p>ID number does not appear to be authentic - check digit is not valid</p>');
correct = false;
};
// if no error found, hide the error message
if (correct) {
error.css('display', 'none');
// clear the result div
$('#result').empty();
// and put together a result message
$('#result').append('<p>South African ID Number: ' + idNumber + '</p><p>Birth Date: ' + fullDate + '</p><p>Gender: ' + gender + '</p><p>SA Citizen: ' + citzenship + '</p>');
}
// otherwise, show the error
else {
error.css('display', 'block');
}
return false;
}
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
$('#idCheck').submit(Validate);
DEMO: http://jsfiddle.net/chridam/VSKNx/
this is the validation regex we us at our company:
string IdExpression = #"(?<Year>[0-9][0-9])(?<Month>([0][1-9])|([1][0-2]))(?<Day>([0-2][0-9])|([3][0-1]))(?<Gender>[0-9])(?<Series>[0-9]{3})(?<Citizenship>[0-9])(?<Uniform>[0-9])(?<Control>[0-9])";
as far as using regex, it's really simple
http://www.w3schools.com/jsref/jsref_obj_regexp.asp
There is a jQuery plugin that you can use. Check it out at http://www.verifyid.co.za/jqueryid
So there is an issue where if the ID number starts with 0 it gives the year of birth 1901 instead of 2001. #louwki mentioned it in his comment
I'm using your code but running into an issues when adding a id number
010101.... it gives the year of birth 1901 instead of 2001 any work around for this?
I have a work around assuming that there is no one older than a 100 years still alive who wants to get their date
// get first 6 digits as a valid date
var tempDate = new Date(idNumber.substring(0, 2), idNumber.substring(2, 4) - 1, idNumber.substring(4, 6));
var id_date = tempDate.getDate();
var id_month = tempDate.getMonth();
var id_year = tempDate.getFullYear();
// Add a 100 years to the current year if older than 100 years
if(id_year < (new Date()).getFullYear() - 100){
id_year+= 100
}
var fullDate = id_date + "-" + id_month + 1 + "-" + id_year;
DEMO: http://jsfiddle.net/dupies/5fwxvu6d/3/
Given a string str, how could I check if it is in the dd/mm/yyyy format and contains a legal date ?
Some examples:
bla bla // false
14/09/2011 // true
09/14/2011 // false
14/9/2011 // false
1/09/2011 // false
14/09/11 // false
14.09.2011 // false
14/00/2011 // false
29/02/2011 // false
14/09/9999 // true
Edit: exact solution below
You could do something like this, but with a more accurate algorithm for day validation:
function testDate(str) {
var t = str.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
if(t === null)
return false;
var d = +t[1], m = +t[2], y = +t[3];
// Below should be a more acurate algorithm
if(m >= 1 && m <= 12 && d >= 1 && d <= 31) {
return true;
}
return false;
}
http://jsfiddle.net/aMWtj/
Date validation alg.: http://www.eee.hiflyers.co.uk/ProgPrac/DateValidation-algorithm.pdf
Exact solution: function that returns a parsed date or null, depending exactly on your requirements.
function parseDate(str) {
var t = str.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
if(t !== null){
var d = +t[1], m = +t[2], y = +t[3];
var date = new Date(y, m - 1, d);
if(date.getFullYear() === y && date.getMonth() === m - 1) {
return date;
}
}
return null;
}
http://jsfiddle.net/aMWtj/2/
In case you need the function to return true/false and for a yyyy/mm/dd format
function IsValidDate(pText) {
var isValid = false ;
var t = pText.match(/^(\d{4})\/(\d{2})\/(\d{2})$/);
if (t !== null) {
var y = +t[1], m = +t[2], d = +t[3];
var date = new Date(y, m - 1, d);
isValid = (date.getFullYear() === y && date.getMonth() === m - 1) ;
}
return isValid ;
}
Try -
var strDate = '12/03/2011';
var dateParts = strDate.split("/");
var date = new Date(dateParts[2], (dateParts[1] - 1) ,dateParts[0]);
There's more info in this question - Parse DateTime string in JavaScript (the code in my answer is heavily influenced by linked question)
Demo - http://jsfiddle.net/xW2p8/
EDIT
Updated answer, try -
function isValidDate(strDate) {
if (strDate.length != 10) return false;
var dateParts = strDate.split("/");
var date = new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]);
if (date.getDate() == dateParts[0] && date.getMonth() == (dateParts[1] - 1) && date.getFullYear() == dateParts[2]) {
return true;
}
else return false;
}
This function passes all the test cases. As far as I'm aware, Adam Jurczyk had posted an accurate answer well before I corrected my original wrong answer. He deserves credit for this.
Demo - http://jsfiddle.net/2r6eX/1/
you can use regular exp to validate date .
try like this :
re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
if(form.mydate.value != '' && !form.mydate.value.match(re))
//do something here
note: this will only work for dd/mm/yyyy
for exact match of your requirement use
re = /^\d{2}\/\d{2}\/\d{4}$/;
I'm going to answer a different question, as Misha Moroshko's has already been well-answered: use HTML5. That is, on the assumption that the strings in question arise as user inputs through a Web browser, I propose that the entries be received as
<input type = "date" ...
I recognize that not all browsers likely to be in use will interpret "date" in a way that rigorously enforces validity. It's the right thing to do, though, will certainly improve as time goes on, and might well be good enough in a particular context even now simply to eliminate the need to validate the date-string after the fact.
Personally, I think the best solution would be to modify the UI to use dropdowns for the month and possibly day selections.
Trying to figure out if 1/2/2001 is January 2nd or February 1st based solely on that input string is impossible.
Recent discovery: You can use date.js lib, it adds function Date.parseExact so you can just do Date.parseExact(dateString,"dd/MM/yyyy"). It fails when month is 00, but its still usefull.
for dd/mm/yyyy format only
^(0?[1-9]|[12][0-9]|3[01])[\/](0?[1-9]|1[012])[\/]\d{4}$