• Home
  • About
  • Resume

JavaScript IsDate(): Validate date according browser locale

By , 07/20/2010 1:40 PM

In one of my recent projects I needed to validate whether user’s input is a valid date, and this needed to be done client-side, in browser prior submission to the server. Lazy as I am, I Googled for a ready-to-use code snippet. There’re plenty of versions out there, but most of them offer incomplete solution and none of them take into account browser locale, you know – the language settings:

So I decided to cook something of my own (more or less). First thing I realized – silly as it is, but you cannot detect browser locale, while in the browser itself (i.e. in JavaScript, concepts such as navigator.language are useless). The only way this data can be retrieved is from HTTP headers sent to the server. But then it can be stored on the page, for example in a hidden field. Following example shows how to do that (I am a fan of ASP.NET, so I am using it, feel free to use language of your choice).

First add following hidden field to your form:

<asp:HiddenField ID="xhidBrowserLocale" runat="server" />

Then add this function to server-side code:

Function GetBrowserLocale() As String

   Dim sLanguages As String() = Request.UserLanguages

   If sLanguages Is Nothing OrElse sLanguages.Length = 0 Then
      Return "en-us"
   End If

   Try
      Dim sLanguage As String = sLanguages(0).ToLower.Trim()
      Return sLanguage
   Catch ex As Exception
      Return "en-us"
   End Try

End Function

and use it to populate the hidden field

xhidBrowserLocale.Value = GetBrowserLocale()

Server-side part is done, the fun part begins. Here’s a simplified modification of amazingly clever JavaScript isDate function from JSFromHell:

function checkDate(y, m, d) { 

    if (typeof(y)=='undefined' || 
        typeof(m)=='undefined' || 
        typeof(d)=='undefined') return 1;

    d = Math.abs(d) || 0, m = Math.abs(m) || 0, y = Math.abs(y) || 0;
    
    return arguments.length != 3 ? 1 : 
           d < 1 || d > 31 ? 2 : 
           m < 1 || m > 12 ? 3 : 
           /4|6|9|11/.test(m) && d == 31 ? 4 :
           m == 2 && (d > ((y = !(y % 4) && (y % 1e2) || 
           !(y % 4e2)) ? 29 : 28)) ? 5 + !!y : 0;
           
}

It takes 3 numeric parameters: year, month and day, checks if their combination is a valid date and if not – returns an error code which can be interpreted by a caller function to display specific error message. The function is smart enough to know how many days in a specific month and even aware of leap years.

And here is the main function that calls the checkDate and interprets error codes:

function isDate(control) {
    var aD = control.value.split("/")
    var iResultCode;
    var sErrorMessage;

    if (document.getElementById('xhidBrowserLocale').value == 'en-gb')
        iResultCode = checkDate(aD[2], aD[1], aD[0])
    else
        iResultCode = checkDate(aD[2], aD[0], aD[1])

    switch (iResultCode) {
        case 1: sErrorMessage = "Invalid date format"; break
        case 2: sErrorMessage = "Invalid day"; break
        case 3: sErrorMessage = "Invalid month"; break
        case 4: sErrorMessage = "In April, June, September and November the month has only 30 days"; break
        case 5: sErrorMessage = "February has only 28 days"; break
        case 6: sErrorMessage = "It's leap year, February has 29 days"; break
    }

    if (sErrorMessage) {
        alert(sErrorMessage);
        control.focus()
    }

}

It accepts a single parameter – HTML input control (for example a text box). Then it splits date from control value into 3 numbers: month, date and year (line 2) – did I mention that this function supports only xx/xx/xx format – feel free to extend it further. After that it checks browser locale (line 6) which was saved by ASP.NET code-behind. This version only detects British English, but more checks can easily be added. So if British English is detected the function calls checkDate and passes second number from input date as a month and first number as a day (29/5/2007 will be checked as checkDate(2007,5,29)). For the rest, including US locale first number from the input date will be passed as a moth and second as a date (2/12/2008 will be checked as checkDate(2008,2,12))

If checkDate returns an error code between 1 and 6, it’s interpreted, error message is displayed to the user and control with error retains focus until correct date is entered. This function can be attached for example to handle onblur event when user entered date and tabs out or clicks Submit button:

Enter date: <input type="text" id="xtxtMyDate" onblur="isDate(this)" />

10 Responses to “JavaScript IsDate(): Validate date according browser locale”

  1. Chakri says:

    Really it’s a good solution…. It’s work perfect.

  2. Chakri says:

    with out any server side code we can’t find the locale date format inside the script? If you have any idea please let me know..

  3. Yuriy says:

    @Chakri As far as I know there’s no client-side detection of the locale, but if I find out a way I will post it here.

  4. Chakri says:

    Thanks.. and now i am getting the locale format by using jQuery.. here i have one query like now i am going to validate the format like dd/mm/yyyy or mm/dd/yyy for this i was done the following changes

    if (da == “dd/MM/yyyy”)
    iResultCode = checkDate(aD[1], aD[0], aD[2])
    else
    iResultCode = checkDate(aD[0], aD[1], aD[2])

    and i was change the checkDate(y, m, d) to checkDate(d, m, y)

    i am getting aD[o]=date, 1=month, 2=year if it is //dd/mm/yyyy

    based on this format i was change the aD[] array values..

    But it’s not works for correct date also it shows wrong format.. i am not sure where i done the mistake.. can you please help me, how to i resolve this?

  5. Chakri says:

    Yuriy i have resolve this issue.. and i have one more query like

    i have a requirement like on selection on date i need to show that date in bellow as DD-MMM-YYYY format.

    Like if the user select 04/08/2010 from date controller then in the below of that field i need to show this date as 04-Aug-2010.

    i don’t have any idea, how to do this? if you have any idea please help me?

  6. Yuriy says:

    @Chakri Should be pretty straightforward, replace “/” with “-” and month number with string representation.

  7. Ciao says:

    There is a simpler way….

    var isDateOrNot = isFinite(Date.parse(myString));

  8. Yuriy says:

    @Ciao, unfortunately doesn’t seem to work universally. For example in IE

    isFinite(Date.parse(’58/79/2011′))

    returns true.

  9. KJ says:

    Thanks Yuriy, but you do not have any year checks? 01/01/9999 or 01/01/mmmm which translates to 01/01/0 pass your edit checks.

  10. Yuriy says:

    @KJ Good point. Function checkDate can use additional checks for validity of “y” parameter (value being numeric and within specific range). Please feel free to post an updated function here so others could benefit

Leave a Reply

Panorama Theme by Themocracy