HiveBrain v1.2.0
Get Started
← Back to all entries
principlejavascriptMinor

Can this date-validation function can be simplified further or is it the correct approach?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thissimplifiedcanthefunctionvalidationdatefurthercorrectapproach

Problem

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

Solution

Can this be simplified ? Most certainly.

  • You can take advantage of the fact that new Date( 'APR 04 1977' ) and new Date( '04 04 1977' ) both work, so you don't need getMonthFromString



  • 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 have element ( simply call val() )



  • isValidDate seems overkill, if you ask for 30 feb 2014, then testDate.getTime() will be NaN



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/

Code Snippets

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');

Context

StackExchange Code Review Q#55981, answer score: 2

Revisions (0)

No revisions yet.