\$\begingroup\$
\$\endgroup\$
4
I am doing a date validation. I have no. of pages, which have the date field. User can input the date like "220875" or "22AUG75" - I need to test both and check the length as well.
function isValidDate(newDate) {
newDate[1] = newDate[1]-1;
newDate[2] = (parseInt(newDate[2]) < 50) ? 2000 + parseInt(newDate[2]) : 1900 + parseInt(newDate[2]);
var testDate = new Date(newDate[2], newDate[1], newDate[0]);
if (testDate.getDate()!=newDate[0] || testDate.getMonth()!=newDate[1] || testDate.getFullYear()!=newDate[2]) {
return false;
} else {
return {valid : true, date : testDate};
}
}
var sandBox = {
init:function(params){
this.element = $(params.element),
this.value = params.value,
this.mode = params.num;
},
isNotEmpty:function(){
if(!this.value.length) {
this.errorHandler(this.emptyMsg);
} else {
this.errorHandler(true);
return true;
}
},
errorHandler: function (msg) {
var errorHolder = this.element.siblings('span');
if(msg !== true)
errorHolder.html(msg).show();
else errorHolder.html("").hide();
},
emptyMsg : "Date field should not be empty",
digitLengthMsg : "The Length of the value should be ",
onlyNumber : {
num : /\D/,
str : /^\d{2}[a-zA-Z]{3}\d{2}$/,
mon : /[a-zA-Z]{3}/,
msg : "Only Digits allowed"
},
getMonthFromString : function(mon){
var month = new Date(Date.parse(mon +" 01, 12")).getMonth()+1;
month = month < 10 ? '0'+ month : month;
return month;
},
isValidData : function () {
var result = this.onlyNumber.str.test(this.value);
if(this.mode && result) {
this.errorHandler(this.onlyNumber.msg)
return false;
}
else if (!this.mode && result) {
var currentMonth = this.getMonthFromString(this.value.match(this.onlyNumber.mon)[0]);
this.value = this.value.replace(/([a-zA-Z]){3}/g, currentMonth);
return true;
}
else if (this.mode && this.value.length !== 6) {
this.errorHandler(this.digitLengthMsg + '6');
return false;
}
else if (!this.mode && this.value.length !== 7) {
this.errorHandler(this.digitLengthMsg + '7');
return false;
}
else {
this.errorHandler(true);
return true;
}
},
DateIsOk:function() {
if(this.isNotEmpty() && this.isValidData()) {
var verifyDate = this.value.match(/.{1,2}/g);
return isValidDate(verifyDate);
}
}
};
var dateValidator = function (e) {
var value = e.target.value;
sandBox.init({
value : value,
element : e.target,
num : true //set month status true means validation by digits, false means digits with string
});
var fieldValue = sandBox.DateIsOk();
if(fieldValue) {
console.log(fieldValue);
}
};
var dateField = $('input');
dateField.on('keyup focusout', dateValidator);
200_success
146k22 gold badges190 silver badges479 bronze badges
asked Jul 3, 2014 at 10:49
1 Answer 1
\$\begingroup\$
\$\endgroup\$
Can this be simplified ? Most certainly.
- You can take advantage of the fact that
new Date( 'APR 04 1977' )
andnew Date( '04 04 1977' )
both work, so you don't needgetMonthFromString
- You can take more out of regexes with capturing groups
- You can get rid of the whole Sandbox construct which does not make a lot of sense to me
- You can write it so that the validator can accept but num:true and num:false, it can only make the user happier ;)
- Not too excited by YY, we spent billions fixing Y2K, and here you come creating more trouble ;)
- You don't need
value
if you haveelement
( simply callval()
) isValidDate
seems overkill, if you ask for 30 feb 2014, thentestDate.getTime()
will beNaN
My counter proposal code is about 1/3rd of yours:
function DateHandler(elementId, _mandatory) {
this.$dateField = $('#' + elementId);
this.mandatory = _mandatory || false;
this.$dateField.on('keyup focusout', this.validate.bind(this));
}
DateHandler.prototype.validate = function () {
this.error('');
var text = this.$dateField.val().toUpperCase(), matches;
if (text.length === 0) {
if (mandatory) {
this.error('Field should not be empty');
}
return;
} else if (text.length == 6) {
matches = /([0-3][0-9])([0-1][0-9])(\d\d)/.exec(text);
} else if (text.length == 7) {
matches = /([0-3][0-9])(\w\w\w)(\d\d)/.exec(text);
}
if (!matches) {
return this.error('Field should be of format DDMMYY or DDMMMYY');
}
value = new Date(matches[2] + ' ' + matches[1] + " " + (matches[3] < 50 ? 20 : 19) + matches[3]);
if (isNaN(value.getTime())) {
return this.error('Not a valid date');
}
console.log(value);
};
DateHandler.prototype.error = function (message) {
var label = this.$dateField.siblings('span');
message ? label.html(message).show() : label.hide();
};
var dateHandler1 = new DateHandler('d1');
var dateHandler2 = new DateHandler('d2');
I tested this fairly well on JsFiddle: http://jsfiddle.net/konijn_gmail_com/985ut/
answered Jul 7, 2014 at 21:30
Explore related questions
See similar questions with these tags.
default
this.mode
represents. I assume it's a toggle between validating220875
and22AUG75
. You should probably rename the variable. If for some reason it is imperative that it stay named like that, please document its behaviour. Also,this.value.match(/.{1,2}/g)
doesn't seem intuitive at all. What exactly do you want to achieve by doing this? \$\endgroup\$User can input the date like "220875" or "22AUG75"
-- why these formats rather than a standard format that people are already familiar with andDate
will recognize? \$\endgroup\$