3
\$\begingroup\$

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

Live Demo

\$\endgroup\$
  • \$\begingroup\$ After a quick glance it's not immediately obvious what this.mode represents. I assume it's a toggle between validating 220875 and 22AUG75. 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\$ – Schism Jul 3 '14 at 16:27
  • \$\begingroup\$ The fiddle says '20BUH74' is valid.. \$\endgroup\$ – konijn Jul 3 '14 at 18:53
  • \$\begingroup\$ Yes. corrected the issues. thanks for you suggestion. And any simplification approach please? \$\endgroup\$ – 3gwebtrain Jul 4 '14 at 5:12
  • \$\begingroup\$ User can input the date like "220875" or "22AUG75" -- why these formats rather than a standard format that people are already familiar with and Date will recognize? \$\endgroup\$ – Dagg Jul 7 '14 at 23:30
2
\$\begingroup\$

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/

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.