Click here to Skip to main content
15,867,453 members
Articles / Web Development / IIS
Article

Date control with support for languages and different date formats

Rate me:
Please Sign up or sign in to vote.
4.14/5 (11 votes)
31 May 20054 min read 93K   713   47   15
Using .NET's System.Globalization class for retrieving month names in forgein lanaguages, and the DateTimeFormatInfo for keeping your dates the correct way around.

Image 1

Introduction

There are many Date controls in the Internet including many here at CodeProject. However few don't tap into .NET's System.Globalization class for retrieving the month names in foreign languages. Names for months in Afrikaans to Vietnamese can be achieved without any knowledge of the spoken language. Furthermore I have also added the possibility to work with any date format I choose. This control works well with US or European date formats. The control also has Visual Studio designer support.

Background

The System.Globalization namespace contains classes that define culture-related information, including the language, the country/region, the calendars in use, the format patterns for dates, currency, and numbers.

I have used the David Truxall control found on CodeProject as a template for the control, along with the following added features:

Properties

PropertyDefault ValueDescription
YearsForward0(Optional) An integer for setting the number of years into the future that the control renders from the current year.
YearsBack0(Optional) An integer for setting the number of years into the past that the control renders from the current year.
Culture(Optional) A string same as Culture Name for displaying the month names. For example, en-gb es-ES. See MSDN for a complete list. If none is set it uses the server's regional code.

- It has no effect on the value of the control.
MonthFormatMMMM(Optional) A string for setting the month text in the control.

Example MMM, MMMM, MM.

- It has no effect on the value of the control.
DateFormat Use the format on the server as defaultA string for setting the output date value format.

For example, dd/MM/yyyy MM-dd-yyyy yyyyMMdd
ValueA value for setting the date.

* Please note if you use dd/MM/yyyy make sure the value is set with double-digits, for example 02/04/2005 is valid while 2/4/2005 is not valid.
SelectCurrentDatetrueA Boolean to set the value to current date when the value is not specified.

Examples for use:

ASP.NET
<%@ Register TagPrefix="cc1" 
  Namespace="i386.UI" Assembly="i386.UI" %>

German with short month text, 10 years into future and two years into the past from the current year:

ASP.NET
<cc1:dropdowndatetime  id="DropDownDateTime1" runat="server" YearsForward="2" 
   YearsBack="10" Culture="de-DE"   SelectCurrentDate="False" MonthFormat="MMM">
</cc1:dropdowndatetime>

US date formatting with the date:

ASP.NET
<cc1:dropdowndatetime id="Dropdowndatetime4" runat="server" 
  dateFormat="MM/dd/yyyy" Value="11/02/2005">
</cc1:dropdowndatetime>

The YearsForward and YearsBack properties can have negative values, which controls the range, as well as the order:

YearsForwardYearsBackYears Displayed
-11201985 ... 1994
11-201994 ... 1985
11201985 ... 2016

How the control works

Firstly, the DateFormat is set to the current one used on the server as default unless the DateFormat properties are set.

C#
private string _DateFormat= 
      System.Threading.Thread.CurrentThread.
             CurrentCulture.DateTimeFormat.ShortDatePattern;        
public string Value 
{
    get 
    {
        string s = (string)ViewState["Value"];
        if(s == null) return String.Empty;
        else return s;
    }                
    set 
    {
        this.SetSelected(value);
        ViewState["Value"] = value;
    }
}


private void SetSelected(string StoredValue)
{
    DateTimeFormatInfo formatInfo = 
                         new DateTimeFormatInfo();
    formatInfo.FullDateTimePattern = DateFormat;
    DateTime dt = DateTime.ParseExact(StoredValue,
                                DateFormat,formatInfo);    
    SelectedDay  = dt.Day;
    SelectedMonth = dt.Month;
    SelectedYear = dt.Year;    
}

The control implements IPostBackDataHandler to manage the resetting of the value of the control when it changes on PostBack. This is the same as David Truxall's except for building of the Value property for the postCollection.

C#
bool IPostBackDataHandler.LoadPostData(string postDataKey, 
     System.Collections.Specialized.NameValueCollection postCollection)
{
    ....
    ....                
    if(this.SelectedDay == -1 && this.SelectedMonth == -1 && 
                                         this.SelectedYear == -1)
        this.Value = "";
    else
    {
        // Build a DateTime string based on the DateFormat
        DateTimeFormatInfo formatInfo = new DateTimeFormatInfo();
        formatInfo.FullDateTimePattern = DateFormat;
        DateTime dt = new DateTime(this.SelectedYear, 
                           this.SelectedMonth, this.SelectedDay);
        this.Value = dt.ToString(DateFormat,formatInfo);
    }
}

Building the child controls

When SelectCurrentDate is set to true (by default) and the Value of the control is left blank we set the control to the current date. We use DateTimeFormatInfo and DateFormat to correctly format the date into a string for the Value property. If SelectCurrentDate is set to false the control is set to January 1st of the first year listed in the year drop box. We use the JavaScript to restrict days on leap years and also to keep the Value input box updated. The Value is kept up to date by the client and server values.

C#
protected override void CreateChildControls()
{
    DateTime dt = DateTime.Today;
    // Use CurrentDate if Value is empty and 
    // SelectCurrentDate is true.
    if (SelectCurrentDate && this.Value=="")
    {
        // Use Current Date
        SelectedDay  = dt.Day;
        SelectedMonth = dt.Month;
        SelectedYear = dt.Year;
        DateTimeFormatInfo formatInfo = 
                               new DateTimeFormatInfo();
        formatInfo.FullDateTimePattern = DateFormat;
        this.Value = dt.ToString(DateFormat,formatInfo);
    }

    // Days
    DropDownList ddlboxDay = new DropDownList();
    ddlboxDay.ID ="Day";
    ddlboxDay.Attributes.Add("onchange",
      "ChangeOptionDays('" + this.ClientID +"',
                              '" + DateFormat + "');");
    for (int nDay = 1; nDay<32; nDay++)
                  ddlboxDay.Items.Add(nDay.ToString());

    
    // So we can restore the Culture later
    CultureInfo ExistingCulture = 
      System.Threading.Thread.CurrentThread.CurrentCulture; 
    // Culture - changes language of months    
    if (Culture!=null)    
      System.Threading.Thread.CurrentThread.CurrentCulture = 
                  new System.Globalization.CultureInfo(Culture);    

    // Months
    DropDownList ddlboxMonth = new DropDownList();
    ddlboxMonth.ID ="Month";
    ddlboxMonth.Attributes.Add("onchange",
      "ChangeOptionDays('" + this.ClientID +"',
                             '" + DateFormat + "');");
    for ( int nMonth=1; nMonth<=12; nMonth++)
    { 
        DateTime MonthDate = new DateTime(2000,nMonth,1);
        ddlboxMonth.Items.Add(new 
              ListItem(MonthDate.ToString(this.MonthFormat),
                                            nMonth.ToString()));
    }
     // Restore 
    System.Threading.Thread.CurrentThread.CurrentCulture = 
                                              ExistingCulture;


    // Years (Forward and Back properties)    
    DropDownList ddlboxYear = new DropDownList();
    ddlboxYear.ID ="Year";
    ddlboxYear.Attributes.Add("onchange",
               "ChangeOptionDays('" + this.ClientID +"',
                                      '" + DateFormat + "');");
    ddlboxYear.ID ="Year";
      if (YearsBack>=0)
      {
        for (int nYear = -YearsBack; nYear<=YearsForward; nYear++)
        {
            int ddlYear =dt.Year+nYear;
            ddlboxYear.Items.Add(ddlYear.ToString());
        }
      }
      else
      {
        for (int nYear = YearsForward; nYear<=-YearsBack; nYear++)
        {
            int ddlYear =dt.Year-nYear;
            ddlboxYear.Items.Add(ddlYear.ToString());
        }
      }

    // Select the DropDownList for the year
    if (SelectedYear>0)
    {
        // See if the year is in the list.
        if (ddlboxYear.Items.FindByValue(SelectedYear.ToString())!=null) 
        {
           ddlboxYear.Items.FindByValue(SelectedYear.ToString()).Selected = 
                                                                        true;
        }
    }
    if (SelectedMonth>0)    
      ddlboxMonth.Items.FindByValue(SelectedMonth.ToString()).Selected = true;
    if (SelectedDay>0)    
      ddlboxDay.Items.FindByValue(SelectedDay.ToString()).Selected = true;

    // Add Child Control
    Controls.Add(ddlboxDay);
    Controls.Add(ddlboxMonth);
    Controls.Add(ddlboxYear);

Debugging mode

It is used to check what is happening with the control. The DebugMode outputs the Value, ViewStates, CultureInfo and DateFormat. To set the DebugMode on, use DebugMode="true".

ASP.NET
<cc1:dropdowndatetime DebugMode=true id="DropDownDateTime1" runat="server">
</cc1:dropdowndatetime>

Image 2

Browser compatibility

This is only a short list of browsers I've tested with. I don't have Netscape installed on my PC.

BrowserUnder OS
Safari 1.0.3
Mac System 9+Fully
Netscape 4.77Mac System 10.2.8No
Opera 6.0.3Mac System 10.2.8Fully
Internet Explorer 5.1, 5.2Mac System 9+Fully
Firefox 1.xWindows XPFully
Internet Explorer 4.0 +Windows XPFully
Netscape ??Windows ??

Internet Explorer 3.0 will need to use server validation. Please let me know if a certain browser doesn't function correctly.

JavaScript support

From the debugging mode you may notice the hidden input box. This Input box can be used in JavaScript before postback is made to the server.

Updates, versions and bug fixes

  • 18th May 2005, Version 0.2
    • Added and fixed the negative values for YearsForward and YearsBack properties.
    • Support for older JavaScript browsers.

Future enhancements

  • Support and testing for old and non/disable JavaScript browsers using server validation.
  • EnableSetDate property is not completed yet. This feature enables/disable the date box by using a checkbox and allows blank dates.
  • Server validation for date and leap year. Included in the source code is a DateTimeValidator.
  • Another feature would be to support a Value whose year is outside the range of YearsForward and YearsBack properties.
  • Time support.

Feel free to comment or add features yourself. If you rate this page lower please leave a comment in the forum below.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Austria Austria
Programmer, Cook, Photographer I guess that's me.

http://www.i386.com

http://blog.glyons.at

Comments and Discussions

 
GeneralGreat job! Pin
bjornhr27-Aug-05 10:05
bjornhr27-Aug-05 10:05 
Just what i was looking for.
Nicely done.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.