Creating a custom DateTime class that allows null values
January 14, 2009I 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#
