Interpret date from text field

  1. User enters something into text area on dialog (vSubSearch).
  2. Program determines if it is a date; if so, performs a search of the likely (date) fields. Otherwise, performs a “contains” search.

The code –

  1. Tests for date format using a global method.
  2. Parses with mod_date.js, then utils.dateFormat to get target_d.
  3. Performs search.

This seems overly complicated. Do I need the “#” and “|”-format when performing the search? In 4D I could test the validity of a date string with one line of code. Am I overlooking something?

Thank you,
Don

function ip_find() {
	var fs = forms.ip_login_incl.foundset;
	if(vSubSearch) {
		if(globals.UTIL_isDateString(vSubSearch)) {	
			var target_d = utils.dateFormat(new Date.parse(vSubSearch), "yyyy-MM-dd");
			fs.find();
			fs.created_d = "#" + target_d + "|yyyy-MM-dd";
			fs.newRecord();
			fs.modified_d = "#" + target_d + "|yyyy-MM-dd";
			var recs = fs.search();
		} else {
			fs.find();
			fs.ip_address = "#%" + vSubSearch + "%";  // contains search, case-insensitive
			fs.search(); 		
		}
	} else {
		fs.loadAllRecords();
	} 
}

Here’s the global test for dates. I tried using just a regex pattern, but the editor flagged it with a bunch of errors. –

function UTIL_isDateString(value) {
    try {
        var MonthIndex = 0;
        var DayIndex = 1;
        var YearIndex = 2;
        var valid_B = true;
 
        value = value.replace(/-/g, "/").replace(/\./g, "/"); 
        var SplitValue = value.split("/");
   
        if (!(SplitValue[DayIndex].length == 1 || SplitValue[DayIndex].length == 2)) {
        	valid_B = false;
        }
        if (valid_B && !(SplitValue[MonthIndex].length == 1 || SplitValue[MonthIndex].length == 2)) {
        	valid_B = false;
        }
        if (valid_B && SplitValue[YearIndex].length != 4) {
        	valid_B = false;
        }
        if (valid_B) {
           var Day = parseInt(SplitValue[DayIndex], 10);
           var Month = parseInt(SplitValue[MonthIndex], 10);
           var Year = parseInt(SplitValue[YearIndex], 10);
 
            if ((Year > 1900) && (Year <= 2100)) {
                if (Month <= 12 && Month > 0) {
                    var leapYear_B = (((Year % 4) == 0) && ((Year % 100) != 0) || ((Year % 400) == 0));
 
                    if (Month == 2) {
                        valid_B = leapYear_B ? Day <= 29 : Day <= 28;
                    }
                    else {
                        if ((Month == 4) || (Month == 6) || (Month == 9) || (Month == 11)) {
                        	valid_B = (Day > 0 && Day <= 30);
                        }
                        else {
                        	valid_B = (Day > 0 && Day <= 31);
                        }
                    }
                }
            }
        }
        return valid_B;
    }
    catch (e) {
        return false;
    }
}

Hi,

Why not let Servoy do all the hard work? :wink:

Give what you have as a initialization parameter to a new Date() and it convert it into a date if possible. First convert the “-” to “/” though or set locale so that it matches. Then all you have to do is test to see if the date is valid.

var s = "2012/01/01";
try {
   var d = new Date(s); 
}
catch(e) {
   application.output(e.message);
}

You get the idea. Hope it helps.

Problem is that JavaScript will happily convert nonsensical values, so Omar’s code above is not enough.

For example, try it with a value of “2012/15/36” and you will see that this converts to Fri Apr 05 00:00:00 EDT 2013 and not raise any exception…

So, one way to make sure that the date was converted correctly is to parse it, then format it as text, then compare the two values.

So a global function like this would do:

function convertDate(s, format) {
    var d = utils.dateFormat(s,format);
    var s2 = utils.dateFormat(d,format);
    if (s2 === s) {
        return d;
    }
    return null;
}

Which you would then call with something like:

var date = globals.convertDate('2012/01/01', 'yyyy/MM/dd');
if (date) { // we successfully converted to date here.
    // do somethind with this date.
}

Hi Patrick,

I tried enhancing your method so that it could tolerate a variety of formats. However, I ran into difficulty because the utils.dateFormat() will accept “6/12/2012” as being in the format “MM/dd/yyyy”. Is there a way around this?

Thanks,
Don

function UTIL_convertDateString(dateString, dateFormat) {
	var testFormat = "";
	var stringResult = "";
	if((dateString) && (dateFormat)) {
		var dateResult = utils.dateFormat(dateString,dateFormat);
	    if(!dateResult) {  // it didn't convert using the specified format
	    	testFormat = "MM/dd/yyyy"
	    	dateResult = utils.dateFormat(dateString,testFormat);
	    }
	    if(!dateResult) { 
	    	testFormat = "MM-dd-yyyy"
	    	dateResult = utils.dateFormat(dateString,testFormat);
	    }
	    if(!dateResult) { 
	    	testFormat = "MM.dd.yyyy"
	    	dateResult = utils.dateFormat(dateString,testFormat);
	    }if(!dateResult) {  
	    	testFormat = "yyyy-MM-dd"
	    	dateResult = utils.dateFormat(dateString,testFormat);
	    }
	    if(!dateResult) { 
	    	testFormat = "yyyy.mm.dd"
	    	dateResult = utils.dateFormat(dateString,testFormat);
	    }if(!dateResult) {  // it didn't convert using the specified format
	    	testFormat = "yyyyMMdd"
	    	dateResult = utils.dateFormat(dateString,testFormat);
	    }
	    if(dateResult) {
	    	if(testFormat) {
	    		stringResult = utils.dateFormat(dateResult,testFormat);
	    	} else {
	    		stringResult = utils.dateFormat(dateResult,dateFormat);
	    	}
		    if (stringResult === dateString) {
		        return dateResult;
		    }
	    }		    
	}
    return null;
}

Hi Don,
I suppose it’s a good thing that it does accept 6/12/2012, because it’s a valid date, if it wasn’t doing this you would have to test for d/MM/yyyy and dd/M/yyyy for each of your formats.
I must say that I never ran into a case where this was an issue, so I never tried to find a better solution.
I suppose a Regexp would be the answer in that case…

Maybe I’m missing something, but could you not use a masked format in your text field in order to force the user to use a specific format? Then you could try mapping the text to a date object via the dateFormat (or dateParse in 6.1 I guess)

utils.dateFormat(vSubSearch, 'yourformat')
``` I seem to remember an error is thrown if the text cannot be parsed...

Hi,

It’s a “smart” search box, that attempts to discern what the user is looking for (see attached). I use this in various locations to allow users to get to a particular record quickly.

Thank you,
Don