Creating a custom DateTime class that allows null values

January 14, 2009

I have a re-occurring hassle with the fact that SQL Server allows the DateTime data type to be NULL, while C# does not. What to do when you’re trying to assign a DateTime property of an object when the underlying data from SQL Server says it’s NULL?

Usually, nothing.

And so then it comes to displaying perhaps a list of these objects and this date property and your web interface is filled with glaringly inaccurate data:

Name Birth date
Joe 7/14/1972
Jim 1/1/0001

Jim didn’t have a birth date in the database, so we never assigned it. Unfortunately it defaulted to 1/1/0001 12:00:00 AM.

Traditionally I would implement some checks on the UI/display side or perhaps during a “…DataBound” event:

If date is a really, really freaking long time ago, display an empty string instead.

And then I finally got tired of that.  Why can’t I just assign NULL to DateTime? What if I created a class that inherited from DateTime and overrode the ToString() method?  Sigh:

  • Date time is a structure and cannot be overridden
  • It can’t ever be NULL
  • It defaults to 1/1/0001 12:00:00 AM (or 0 ticks) which is the same as DateTime.MinValue

So what about a custom class that includes an internal DateTime member, and encapsulates the logic of determining that if it’s value is 1/1/0001, it probably isn’t accurate and thus it should output an empty string whenever it must be displayed.  Something like:

public class Dtime
{
    private DateTime _datetime; //equals the min value by default

    public Dtime()
    {
        //constructor
    }

    public override string ToString()
    {
        if (_datetime.Equals(DateTime.MinValue))
            return "";
        else
            return _datetime.ToString();
    }
}

That’s pretty much it. Now when it comes time to display a property of Dtime which was never constructed (or explicitly constructed as a “null” date) it will simply output nothing instead of 1/1/0001, which we’re assuming is never valid.

The complete class is available below (click + expand source). I’ve created some additional helpful methods, and there actually is a constructor that accepts a DateTime, string or NULL parameter.

/// <summary>
/// Custom "DateTime" class that allows for assignment of NULL values. ToString() methods return
/// the inner DateTime's respective value to a string, or return an emptry string if the object contains
/// a null inner DateTime value.
/// </summary>
[Serializable]
public class Dtime
{
    private DateTime _datetime; //equals the min value by default

    /// <summary>
    /// Creates instance of custom "DateTime" object. Pass either a DateTime type or NULL to instantiate
    /// </summary>
    /// <param name="d">A DateTime type or NULL object</param>
    public Dtime(object d)
    {
        if (d != null)
        {
            DateTime dtemp;
            try
            {
                dtemp = Convert.ToDateTime(d);
                //valid date
                _datetime = dtemp;
            }
            catch
            {
                //invalid date, see if it's a string we can parse instead
                try
                {
                    dtemp = DateTime.Parse(d.ToString());
                }
                catch
                {
                    //not a valid date string either, so not a date; _datetime will default to min value
                }
            }
        }
    }

    public DateTime DateTimeObject
    {
        get { return _datetime; }
    }

    /// <summary>
    /// Evaluates whether date is valid. DateTime.MinValue (1/1/1900) IS NOT considered valid!
    /// </summary>
    /// <returns></returns>
    public bool IsValidDate()
    {
        if (_datetime.Equals(DateTime.MinValue))
            return false;
        else
            return true;
    }

    public string ToShortDateString()
    {
        if (_datetime.Equals(DateTime.MinValue))
            return "";
        else
            return _datetime.ToShortDateString();
    }

    public override string ToString()
    {
        if (_datetime.Equals(DateTime.MinValue))
            return "";
        else
            return _datetime.ToString();
    }

    /// <summary>
    /// Formats object as string
    /// </summary>
    /// <param name="format">The format pattern.
    /// Some common patterns (based on Wed Nov 19, 2008 1:18:54PM) :
    /// yyyy = 2008 | MMMM = November | MMM = Nov | MM = 11 |
    /// dddd = Wednesday | ddd = Wed | dd = 19 |
    /// HH:mm = 13:18 | hh:mm tt = 01:18 PM | ss = 54
    /// </param>
    /// <returns>string</returns>
    public string ToString(string format)
    {
        if (_datetime.Equals(DateTime.MinValue))
            return "";
        else
            return _datetime.ToString(format);
    }
}

Tags: datetime, null, custom class
Categories: C#

blog comments powered by Disqus

About me

I'm a consultant with Headspring in Austin, TX. My passion is creating web-based applications that are well crafted and solve real problems for real people. Want to know more? Check out my about page.

WTF is all this code? I came here for food!

My wife made a new year's resolution to try out at least one new recipe each week. Want to know what she's been feeding me? resolutionfood.blogspot.com