Today we are going to add a custom Date parsing routine to the JQueryUI Date Picker so it automagically parses dates in a variety of formats.
Back in August of 2020, I wrote an article showing you how to incorporate the JQueryUI Date Picker into your WebDev applications. If you have read that article be sure to read it first, as this article will just cover extending the functionality.
I ended that article with a suggestion that it should be possible to write your own date parsing function and integrate that with the Data Picker to have a WEBDEV date control that would be better than sliced garlic cheese bread.
Well no one took up the mantle, or if they did they didn’t share the results with me. Today we had a client that really needed their date controls to feature the parsing logic, so now we have it!
First the Date Parsing Logic, it has to be browser based code, and we could like it to be able to accept dates in almost any format you could dream up, and return the date in standard YYYYMMDD format. It needs to support both Day/Month/Year and Month/Day/Year formats, and it needs to intelligently convert 2 digit years to 4 digits
Here is a trace log from my testing procedure, as you can see that is a lot of formats it handled. The function has two flags. DayFirst tells the logic to expect the date with the day first. You can see there are separate testing sections for each. The other flag is NoFutureDate, which tells the logic to assume the date is always in the past, for example, birth date fields. This affects the rollover logic for two digit years, notice 01/16/24 returns 2024 with this option off, but 1924 with it on. The rollover logic without the NoFutureDate flag assumes anything within 20 years into the future is a future date, otherwise it is a past date.

This function is actually quite long by WEBDEV standards at 133 lines but it is doing quite a bit in those 133 lines. I won’t go into detail on the logic as it isn’t the point of this article but hopefully, you can follow it, if you have any questions just let me know
PROCEDURE ParseDate(LOCAL inDate is string ,LOCAL NofutureDate is boolean=False,DayFirst is boolean = False)
IF inDate = "" THEN
RESULT ""
END
inDate = NoSpace(inDate)
tmpdate is Date
IF DateValid(inDate) THEN
// Passed in YYYYMMDD format so just format it
tmpdate = inDate
ELSE
FirstPart is string
SecondPart is string
ThirdPart is string
arrMonth is array of 12 strings
tmpdate = "19990101"
FOR x = 1 TO 12
arrMonth[x] = Replace(DateToString(tmpdate,"MMM"),".","")
tmpdate..Month++
END
IF Position(inDate,"/") > 0 OR Position(inDate,".") > 0 OR Position(inDate,"-") > 0 OR Position(inDate," ") > 0 THEN
// If there is a separator parse into 3 fields
FirstPart = ExtractString(inDate,1,["/",".","-"," "])
SecondPart = ExtractString(inDate,2,["/",".","-"," "])
ThirdPart = ExtractString(inDate,3,["/",".","-"," "])
// Need to figure out if they entered month abbreviation, and convert to #
tmpMonth is string
IF DayFirst THEN
tmpMonth = SecondPart
ELSE
tmpMonth = FirstPart
END
IF Length(tmpMonth) > 2 THEN
tmpMonthNo is int = ArraySeek(arrMonth,asLinearFirst+tccIgnoreCase,tmpMonth)
IF tmpMonthNo > 0 THEN
tmpMonth = NumToString(tmpMonthNo,"02d")
END
IF DayFirst THEN
SecondPart = tmpMonth
ELSE
FirstPart = tmpMonth
END
END
ELSE
// No separator parse into 3 fields based on length
SWITCH Length(inDate)
CASE 4
// No Year - Assume current
FirstPart = inDate[[1 TO 2]]
SecondPart = inDate[[3 TO 4]]
ThirdPart = CurrentYear()
CASE 6
// 2 digit year
FirstPart = inDate[[1 TO 2]]
SecondPart = inDate[[3 TO 4]]
ThirdPart = inDate[[5 TO 6]]
CASE 8
// 4 digit year
FirstPart = inDate[[1 TO 2]]
SecondPart = inDate[[3 TO 4]]
ThirdPart = inDate[[5 TO 8]]
END
END
IF ThirdPart = EOT THEN
ThirdPart = ""
END
// Build Date - Assume current year for now
tmpdate = Today()
//tmpdate..Year = CurrentYear()
IF DayFirst THEN
IF SecondPart > 0 AND SecondPart < 13 THEN
tmpdate..Month = SecondPart
ELSE
RESULT ""
END
IF FirstPart > 0 AND FirstPart < 32 THEN
tmpdate..Day = FirstPart
ELSE
RESULT ""
END
ELSE
IF FirstPart > 0 AND FirstPart < 13 THEN
tmpdate..Month = FirstPart
ELSE
RESULT ""
END
IF SecondPart > 0 AND SecondPart < 32 THEN
tmpdate..Day = SecondPart
ELSE
RESULT ""
END
END
// Now we need to figure out the century for the year
SWITCH Length(ThirdPart)
CASE 2
tmpYear is string = CurrentYear()
tmpCentry is string = Left(tmpYear,2)
tmpYear = Right(tmpYear,2)
IF Val(ThirdPart) > Val(tmpYear) + 20 THEN
// if more than 20 years in future assume its a past date
ThirdPart = NumToString(Val(tmpCentry)-1,"02d") + ThirdPart
ELSE
ThirdPart = NumToString(Val(tmpCentry),"02d") + ThirdPart
END
tmpdate..Year = ThirdPart
IF NofutureDate AND tmpdate > Today() THEN
// if NofutureDate (DOB) assume its a past date
tmpdate..Year -= 100
ELSE
ThirdPart = NumToString(Val(tmpCentry),"02d") + ThirdPart
END
CASE 4
tmpdate..Year = ThirdPart
CASE 0
tmpdate..Year = CurrentYear()
OTHER CASE
RESULT ""
END
END
// Return results
IF DateValid(tmpdate) THEN
RESULT tmpdate
ELSE
RESULT ""
END
Fortunately using the function is much more straightforward, in the exit with changes browser event of the edit control we have attached to the date picker we place this code
tmpHold is string = edtDemoDateDisplay
edtDemoDateDisplay = DateToString(edtDemoDate,"MM/DD/YYYY")
IF tmpHold <> edtDemoDateDisplay THEN
// They keyed in the date instead of using the date picker
//edtDemoDate = ParseDate(tmpHold,True,false) // No future dates - handles 2 digit year rollovers as being in the past - i.e. 010124 will be 1924 not 2024 - Good for Birthdays
edtDemoDate = ParseDate(tmpHold,False,False) // with future dates - handles 2 digit year rollovers as being in the future if within 20 years - i.e. 010124 will be 2024 not 1924, but 010154 will be 1954
edtDemoDateDisplay = DateToString(edtDemoDate,"MM/DD/YYYY")
END
tmpHold saves what is in the edit control
Next, we format the value in our hiddle control that is populated via the Date Pickers altField option. This value is in YYYYMMDDD so WEBDEV can handle it as a date variable
If they selected a date from the calendar then tmpHold and edtDemoDate will have the same value and we are done, if not, then we use the ParseDate function to populate our hidden control based on what the user typed into edtDemoDateDisplay. Note there are two sample calls, depending on if this field is likely to have future dates or not.
And now we have date control that is attractive and allows the user to select a date from a very functional calendar, or key the date in almost any imaginable format.
I have a sample page showing this control published at demo.wxperts.com if you would like to see it in action.
You can also download our wxDemov27 program from Dropbox which contains this demo page and code.
One thought on “Adding a Custom Date Parser to jQueryUI’s Date Picker”