分享方式:


Adding Emptiness to the DateTime class

I got an interesting email from a customer today, asking for my opinion on how to deal with the concept of “Empty” in relation to DateTime values. They had decided to use the DateTime.MinValue value as an indication that the DateTime was empty.

The two options they were consider were:

1) Call static functions to determine whether a DateTime is empty
2) Just compare the DateTime value to DateTime.MinValue to see if it is empty.

After a bit of reflection, I decided that I didn't like either approach. The problem is that they're trying to add a new concept of “emptiness” (some might equate this to “null”) to a type without changing the type.

A better approach is to define a new type that supports the concept of emptiness. In this case, we'll create a struct that encapsulates the DateTime value and lets us deal with empty in a more robust manner.

Here's the struct I wrote for them (and, no, this is not an indication that I'm now writing classes when people ask me to). 

 public struct EmptyDateTime
{
    DateTime dateTime;

    public EmptyDateTime(DateTime dateTime)
    {
        this.dateTime = dateTime;
    }

    public bool IsEmpty
    {
        get 
        {
            return dateTime == DateTime.MinValue;
        }
    }

    public static explicit operator DateTime(EmptyDateTime emptyDateTime)
    {
        if (emptyDateTime.IsEmpty)
            throw new InvalidOperationException("DateTime is Empty");
        return emptyDateTime.dateTime;
    }

    public static implicit operator EmptyDateTime(DateTime dateTime)
    {
        return new EmptyDateTime(dateTime);
    }

    public static EmptyDateTime Empty
    {
        get
        {
            return new EmptyDateTime(DateTime.MinValue);
        }
    }
}

Comments

  • Anonymous
    March 23, 2004
    Agree, this is a nice approach to this problem. This has been taken a bit further by the NullableTypes project: http://nullabletypes.sourceforge.net/
  • Anonymous
    March 23, 2004
    The comment has been removed
  • Anonymous
    March 23, 2004
    If you are going to all the effort of creating a new class, why not use an extra bool instead of DateTime.MinValue?
  • Anonymous
    March 23, 2004
    How will this integrate with third party UI controls?
  • Anonymous
    March 23, 2004
    Steven,

    You could use an extra bool instead of a specific value, if you were willing for your types to be bigger.

    That may be a reasonable tradeoff in some situations.

    Thomas, the answer to your question is probably "not too well".
  • Anonymous
    March 23, 2004
    I'm not really fond of the name, though, as the struct isn't necessarily empty; it's empty-able, although a better name escapes me
  • Anonymous
    March 23, 2004
    The comment has been removed
  • Anonymous
    March 23, 2004
    What about System.Data.SqlTypes.SqlDateTime ?
    Isn't it what it's all about ?
  • Anonymous
    March 23, 2004
    In our company we use an approach that was published in the Visual Basic Programmer's Journal in 2000. The article is availabe online via MSDN at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvbpj00/html/nullvalues.asp

    The idea is called the "Alias Null concept", where a constant value acts as a surrogate for a database NULL value.

    We have implemented a utility class NullValue that offers operations like bool IsNullAlias(object val) to check, if a current value is a Null Alias. Our windows forms data binding takes care of this, so database NULL values will be displayed correctly.

    Our persistence framework converts database NULL values into Alias Nulls when reading data in and writes database NULL values into the database when properties of persistent objects have an Alias Null value. Works pretty well for us.
  • Anonymous
    March 23, 2004
    I did like Eric but took Sql Server's MinDate instead of DateTime.MinDate.
  • Anonymous
    March 23, 2004
    SqlTypes are not serializable (AFAIK). They're also bound to SQL Server (duh!), which is no use if you need to use another DB.
  • Anonymous
    March 23, 2004
    I have to admit, I don't like this issue either. This is probably the only thing that irks me when it comes to dealing with value types.

    I can't admit to having a solution (having a new type that encapsulates the value type doesn't seem right, unless it is provided in the System namespace).

    Also, implementing INullable on value types doesnt seem like it would work either.

    For the solution you provided, you should have implemented INullable for completeness.

    Also, you could have recommended that they use the SqlDateTime structure, whcih provides null semantics.
  • Anonymous
    March 23, 2004
    I have done something similar in my own business objects. The next step for your own nullable type is to implement IComparable so that you can sort on this column and IConvertible will allow you to pass this type directly to command objects and the like.

    Of course for databinding for a property named BornOn of class Budweiser, binding will look for a property called BornOnIsNull to determine if its null or not, so going forward I've come to the conclusion that I should not expose my custom nullable types outside of my business objects, just use them internally.

    Paul
  • Anonymous
    March 23, 2004
    Nicholas: IConvertible lets a value type tell a command object its DBNull.Value.
  • Anonymous
    March 24, 2004
    Dietmar,

    The http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvbpj00/html/nullvalues.asp is talking about VB 5/6 - in which this isn't really a major issue, since you would just use a Variant (which can handle Null).

    Seeya
  • Anonymous
    March 24, 2004
    Make you yearn for a generic called Nullable<T>. ;-)
  • Anonymous
    March 24, 2004
    So why is DateTime sealed?

    This would do the trick if it weren't:

    public class EmptyDateTime : DateTime
    {
    private EmptyDateTime() {}
    public static EmptyDateTime Empty;
    }

    I have not worked with value types, so it could be the singelton pattern doesn't work here, or the Equals method must be overridden.
  • Anonymous
    March 25, 2004
    I like the solution, but that name of 'EmptyDateTime' is quite ugly and missleading.

    It should've been NullableDateTime or something like that.

  • Anonymous
    April 01, 2004
    The comment has been removed
  • Anonymous
    July 21, 2004
    Or you could just hold your breath for another 8 mo. or so and use .NET 2.0 with their nullable types (or jump into the beta):

    DateTime? dt=new DateTime();

    and then

    if (dt.HasValue)
    {
    }
  • Anonymous
    December 27, 2004
    [http://itpeixun.51.net/][http://aissl.51.net/][http://kukuxz003.freewebpage.org/][http://kukuxz001.51.net/][http://kukuxz003.51.net/][http://kukuxz005.51.net/][http://kukuxz002.51.net/][http://kukuxz004.freewebpage.org/][http://kukuxz007.51.net/][http://kukuxz001.freewebpage.org/][http://kukuxz006.51.net/][http://kukuxz002.freewebpage.org/][http://kukuxz004.51.net/][http://kukuxz008.51.net/][http://kukuxz009.51.net/][http://kukuxz005.freewebpage.org/][http://kukuxz006.freewebpage.org/][http://kukuxz007.freewebpage.org/][http://kukuxz009.freewebpage.org/]
  • Anonymous
    July 07, 2006
    PingBack from http://planetzack.wordpress.com/2006/07/07/nullable-types/
  • Anonymous
    April 30, 2007
    PingBack from http://mgvinod.wordpress.com/2006/08/03/datetime-and-isempty/