Have an idea?

Visit Sawtooth Software Feedback to share your ideas on how we can improve our products.

Date validation

Hi all

I'm using the calendar question from the library, allowing folk to either enter the date directly or enter from the calendar.  I want to verify that what they enter is a valid date (ie not after today).  

When I enter a date that's not valid, it lets me through, but just saves it as if I entered today's date.  What I'd like is an error message to come up.  Can someone help please?  Here's what I have:

var now = Date.now();

if (!$('#[% QuestionName() %]_Unix').val()) {
    strErrorMessage = 'A response is required.';
}

if (SSI_GetValue('Calendar_Unix') > now){
    strErrorMessage = "You can't enter a date that is in the future.";
}
asked Jan 18 by Marion Silver (5,240 points)
AHA!  I should be using UserInput rather than Unix.  If I enter any numbers AT ALL, even if it isn't a date, it's allowed through.  So first of all, I need to make sure the ONLY dates are allowed to be entered.  Then I can validate against today's date.
Yeah, respondents being able to freely type into the input opens a big can of worms once you consider the possibility of bad input.  I gave the input element the "readonly" attribute by default to avoid this altogether.

There wasn't an easy way for me to write custom verification to test that user-written input is valid because the question supports any arbitrary date format, but it shouldn't be too hard to write some specific validation code if I know exactly what date format you are using.
Cheers, Zachary!  I'd be after dd/mm/yyyy date format.

1 Answer

0 votes
 
Best answer
Please try out this verification:

// Settings
var invalidFormat = 'Response was not recognized as a date.';
var invalidDate = 'Response was not a real date.';
var futureDate = 'Response cannot be a future date.';

// Run
var resp = $('#[% QuestionName() %]_UserInput').val();
var match = resp.match(/^\s*(\d{1,2})\/(\d{1,2})\/(\d{1,4})\s*$/);

if (!match) {
    strErrorMessage = invalidFormat;
}

else {
    var day = Number(match[1]);
    var month = Number(match[2]);
    var year = Number(match[3]);
    
    var maxDay = 31;
    switch (month) {
        case 4:
        case 6:
        case 9:
        case 11:
            maxDay = 30;
            break;
        case 2:
            maxDay = 28;
            if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
                maxDay = 29;
            }
            break;
    }
    if (day < 1 || day > maxDay || month < 1 || month > 12) {
        strErrorMessage = invalidDate;
    }
    else if (new Date(year, month - 1, day) > new Date()) {
        strErrorMessage = futureDate;
    }
}
answered Jan 18 by Zachary Platinum Sawtooth Software, Inc. (202,300 points)
selected Jan 19 by Paul Moon
Wow!  That's great, Zachary!  Now I'm guessing I take the UserInput, turn it into Unix, and then compare to today's date.  I'll give that a crack.
So 31/01/2022 triggers the futureDate error.  31/1/2022 does too.  But 31/1/22 goes through.
So we need to support two-digit years?  One catch with that is interpreting whether that represents the current century or the last - "40" could be the past date 1940 or the future date 2040.  Is there a minimum date you are allowing for your calendar question that we could use as a cutoff to make this determination?
Or I could force the date to be in dd/mm/yyyy format?
That would certainly simplify matters.  Please try adjusting line 8 to look like this:

var match = resp.match(/^\s*(\d{1,2})\/(\d{1,2})\/(\d{4})\s*$/);
Thanks a heap.  Perfect.
Date validation in a dropdown calendar (date picker)
...