South African ID Number Validate and Get Age and Gender - javascript

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/

Related

I'm trying to find the highest mark and lowest mark in an array with prompts

So my teacher assigned us an assignment to make a program to find the highest and lowest mark of a maximum of 15 students. So it's possible to put in less than 15 students. The user must input the student's name and after the student's mark. After all the student's names and marks have entered, it's suppose to compare the marks to find the least and the greatest.
CODE:
var Students = ["sn1", "sn2", "sn3", "sn4", "sn5", "sn6", "sn7", "sn8", "sn9", "sn10", "sn11", "sn12", "sn13", "sn14", "sn15"]; //student's name array
var Marks = ["sm1", "sm2", "sm3", "sm4", "sm5", "sm6", "sm7", "sm8", "sm9", "sm10", "sm11", "sm12", "sm13", "sm14", "sm15"]; //student's marks array
Students[0] = prompt("Student 1's name.");
if(Students[0].length == 0) {
Marks[0] = null
} else {
Marks[0] = prompt("Student 1's mark."); //I just copied and pasted this 15 times and changed the [0] to the next number.
while(isNaN(Marks[0]) || Marks[0] >= 101 || Marks[0] <= -101) { //if number is greater than or equal to 101, or less than or equal to -1. Prevents a mark higher than 100 and less than 0.
window.alert("Please input a number between 0-100.");
Marks[0] = 0
Marks[0] = prompt("Student 1's mark."); //reprompt.
}
}
console.log(Students[0] + " " + Marks[0]); //displays mark.
var greatest = -100; //my friend did this part so I don't know if it's right.
var least = 100;
var trackg = 0;
var trackl = 0;
if (Marks[x] != null){ //if this isn't here then I get an error with null.length can't be measured below.
for(var x = 0; x < Marks.length; x ++) {
if(Marks[x].length == 2) {
" " + Marks[x];
}
if(Marks[x] >= greatest && Marks[x] != null) {
greatest = Marks[x]
trackg = x
}
}
}
for(var j = 0; j < Marks.length; j ++) { //the marks[x] != null doesn't work here. it will show that the greatest number is the least number as well which it isn't.
if (Marks[j] <= least && Marks[j] != null){
least = Marks[j];
trackl = j;
}
}
console.log(Students[trackg] + " has the highest mark of " + Marks[trackg] + ". " + Students[trackl] + " has the lowest mark of " + Marks[trackl] + ".");
PROBLEMS:
1. When it compares the number it just takes the first number as the largest number and that's it. So lets say I put the first student's mark as 99 and after I put the 2nd student's as 100. It says 99 is the highest mark and same with negatives for the lowest.
2.I also get that if I put in 100, numbers like 29, 99, etc are higher numbers due to 1 < 2 or 9 etc.
3.For negative numbers, If I put -13 and -99, -13 says it's the lowest which it isn't.
Also, if I put in 10 and 100 (even as negatives), 10 is greater/ the least.
I've tried so many things and I don't know whats wrong. (Btw this is my first time with javascript). This assignments due Monday. Thanks ;A;
This is an example of how you could do it. Note how the validation is done, and conversion of user input to an actual number for comparison. Only one main loop is necessary; the while loops are to ensure the user enters valid data.
You do not need to actually store all the students' data as an array to display the highest and lowest result.
var students = [];
var numOfStudents, highest = { mark:-1 }, lowest = { mark:101 };
// Get number of students between 1 and 15
while (isNaN(numOfStudents) || numOfStudents <= 0 || numOfStudents > 15)
numOfStudents = parseInt(prompt('How many students? (1-15)', '1'), 10);
// For each student, get the name and mark
for (i = 1; i <= numOfStudents; i++) {
var student = {};
while (typeof student.name === 'undefined' || student.name == '')
student.name = prompt('Enter Student '+i+' name:', '');
while (typeof student.mark === 'undefined' || isNaN(student.mark) || student.mark < 0 || student.mark > 100)
student.mark = parseFloat(prompt('Enter Student '+i+' mark (0-100):', ''));
// Check if highest or lowest
if(student.mark > highest.mark) highest = student;
if(student.mark < lowest.mark) lowest = student;
// Save current student to the list (optional)
students.push(student);
}
// Display result
document.body.innerHTML = highest.name + " has the highest mark of " + highest.mark + ". " + lowest.name + " has the lowest mark of " + lowest.mark + ".";

JQuery setting a number format

I'm using JQuery and I'm having a problem trying to sort out how to increase a number.
The record number is something like 1364-14-1234.
The number format works like this:
1364 - Member number
14 - Year in 2 digit format
1234 - in the number which needs to be increased.
The problem is how do I add a leading zero to the number to keep a 4 digit number if the number is 0123.
<div id="member_id">1364-14-0001</div>
var data = $('#member_id').text();
var arr = data.split('-');
var num = arr[2];
num++;
$("#member_id").html(arr[0] + " - " + arr[1] + " - " + num);
My JSfiddle
Something like this maybe
function pad(numb, len) {
while (numb.toString().length < len) numb = '0' + numb;
return numb;
}
$('#member_id').text(function(_, txt) {
var arr = txt.split('-'),
len = arr[2].length;
arr[2] = pad(+(arr[2]) + 1, len);
return arr.join('-')
});
FIDDLE

Counter is not updated and it's value is replaced by the current value

I'm using 4 drop-down lists in an html form. The 2 drop downs, represent the starting and ending month of an activity and the other 2 represent the starting and the ending year of an activity. I'm allowing the user to enter a 3 year history and after completion, I prompt the user to go to the next section. To calculate the 3 year history, I take the difference between the start and ending month and I enter it each time in a counter (note that I am working with numbers and not with the Date object). The values are passed into my arrays, but the counter is not updated. It is just replaced by the new value in the array. Can anyone tell me where is the problem? Here is my code:
var arrMonthStarted = []; //It stores the month that activity started
var arrMonthEnded = []; //It stores the month that activity ended
var arrYearStarted = []; //It stores the year that activity started
var arrYearEnded = []; //It stores the year that activity ended
function validatedropdowns1(){
var monthStarted = document.getElementById('idMonthStarted').value;
var yearStarted = document.getElementById('idYearStarted').value;
var monthEnded = document.getElementById('idMonthEnded').value;
var yearEnded = document.getElementById('idYearEnded').value;
arrMonthStarted.push(monthStarted);
arrMonthEnded.push(monthEnded);
arrYearStarted.push(yearStarted);
arrYearEnded.push(yearEnded);
//Calculating the 3-year history
var count = 0;
if(yearStarted == yearEnded){
if(monthEnded < monthStarted){
var temp = monthEnded;
monthEnded = monthStarted;
monthStarted = temp;
}
var diffmonths = monthEnded - monthStarted;
count = count + diffmonths;
}
//Take the difference between the years.
var subYears = yearEnded - yearStarted;
//If 1, just take the difference on the first 2 lines of the calendar
if(subYears == 1){
var subLine1 = 12 - monthStarted;
var subLine2 = 12 - monthEnded;
var finalLine2 = 12 - subLine2;
var takeresult = subLine1 + finalLine2;
count = count + takeresult;
}
//Follow case 1, but also add 12 months
if(subYears == 2){
var subLine3 = 12 - monthStarted;
var subLine4 = 12 - monthEnded;
var finalLine3 = 12 - subLine4;
var takeresult11 = subLine3 + finalLine4;
var takeresult1 = 12 + takeresult11;
count = count + takeresult1l;
}
//add another 12 months (24 now) on step 1.
if(subYears == 3){
var subLine5 = 12 - monthStarted;
var subLine6 = 12 - monthEnded;
var finalLine5 = 12 - subLine6;
var takeresult22 = subLine5 + finalLine6;
var takeresult2 = 24 + takeresult22;
count = count + takeresult2;
}
var arrCount = []; // array to hold the count var
arrCount.push(count); // push count into arrCount
//print total months
for(var m = 0; m < arrCount.length; m++){
alert("The array now has" + "" + "" + count + "" + "months");
}
if(arrCount == 36){
alert("You have successfuly finished this section. Please go to the next section. Thank you.")
document.getElementById('btnAdd').disable = true;
}
if(arrMonthEnded[arrMonthEnded.length - 1] - arrMonthStarted[arrMonthSarted.length] > 1){
alert("There should not be a gap of more than a month in your 3 year activity. Fill in all the months and select from the list what you were doing each month. Thank you.")
}
}
Also, I was trying to test the gap between the end date and the next start date. For example if I enter 12 2011 as an end date and 03 2012 as the next start date, I would like to see if there is a gap of more than one month. I tried the code below, but it didn't work
if(arrMonthEnded[arrMonthEnded.length - 1] - arrMonthStarted[arrMonthSarted.length] > 1){
alert("There should not be a gap of more than a month in your 3 year activity. Fill in all the months and select from the list what you were doing each month. Thank you.")
}
Thank you in advance (KSFIDDLE http://jsfiddle.net/k4dNb/)
This loop is pointless, as the array will only ever have one item:
for(var m = 0; m < arrCount.length; m++){
Here you are comparing an array to a number, and eventhough that actually works because both will be converted to strings, and the string value of [36] is "36" which is the same as the string value of 36 which is "36", it's done in a confusing way:
if(arrCount == 36){
Typo, you wrote arrMonthSarted instead of arrMonthStarted:
if(arrMonthEnded[arrMonthEnded.length - 1] - arrMonthStarted[arrMonthSarted.length] > 1){
Also, arrMonthStarted[arrMonthStarted.length] will always return undefined, as you are trying to access an item beyond the last item of the array.

JavaScript Math to PHP Page ID

I'm trying to create a form that takes a birthdate, adds up all the digits, then uses the result to query the database and display the results. The sum has to be a number between 1 an 22 in order for it to choose from the database.
I have the form button to trigger the function getBirthCard, but on click it simply spits the value of the form inputs into the URL.
Can anyone give me an idea of what's not coded properly in order for this to work? Please and thank you!
<script language="JavaScript" type="text/javascript">
function getBirthCard() {
var month = lpn.month.value;
var day = lpn.day.value;
var Byear = lpn.year.value;
var century = Byear.substring (0,2);
var year = Byear - century*100;
sum = parseInt(day) + parseInt(month) + parseInt(century) + parseInt(year);
reduce();
results(sum);
}
function reduce(){
var first; // first one or two digits
var last; // last digit
var sumStr = "" + sum;
// while number is bigger than 22
while (sum > 22) {
// if it is a three digit number
if (sum > 99) {
first= sumStr.substring(0,2);
last= sumStr.substring(2);
sum = parseInt(first) + parseInt(last);
sumStr = "" + sum;
// if it is a two digit number
} else {
first= sumStr.substring(0,1);
last= sumStr.substring(1);
sum = parseInt(first) + parseInt(last);
sumStr = "" + sum;
}
} // end while
} // end reduce
}
function results()
{
window.location.assign("http://arcanabazaar.com/results.php?id=' + sum")
}
</script>
Here's the form that I'm using:
<form class="form-inline" action="" name="lpn" method="GET">
<input type="text" id="month" name="month" placeholder="08">
<input type="text" id="day" name="day" placeholder="20">
<input type="text" id="year" name="year" placeholder="1987">
<br><br>
<button type="submit" onclick="getBirthCard()" class="btn btn-large">What's My Card?</button>
</form>
I'm guessing you're choosing a card from the major arcana based on the birthday digits. If you don't care too much about how this is calculated, here's a quick way to do it using modular arithmetic:
function getBirthCard() {
var month = document.getElementById("month").value;
var day = document.getElementById("day").value;
var year = document.getElementById("year").value;
var sum = parseInt(month) + parseInt(day) + parseInt(year);
var card = sum % 22 + 1; // this is always from 1 to 22
window.location.assign('http://arcanabazaar.com/results.php?id=' + card);
return false;
}
The button to call this must be coded as:
<button type="submit" onclick="return getBirthCard();" class="btn btn-large">What's My Card?</button>
The OnClick event must return false, so that it doesn't continue to actually submit the form. That's why it was sending the month, day, year values directly previously.
This will give different results than your code was intending, but perhaps this will suffice.
(EDIT: Replaced lpn.month.value by document.getElementById("month").value etc.)
(EDIT2: Return false to onclick caller.)
EDIT3: Here's code to repeatedly add the digits together until they are less than or equal to 22:
function getBirthCard() {
var month = document.getElementById("month").value;
var day = document.getElementById("day").value;
var year = document.getElementById("year").value;
var card = getCardFromDate( month, day, year );
window.location.assign('http://arcanabazaar.com/results.php?id=' + card);
return false;
}
function getCardFromDate( month, day, year )
{
var sum = parseInt('' + month + day + year);
while( 22 < sum )
{
var digits = (''+sum).split('');
sum = 0;
for( var i=0 ; i<digits.length ; ++i ) sum += parseInt(digits[i]);
}
return sum;
}

JS Date Validation Enhancement

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()

Categories