320

How do you deal with a DateTime that should be able to contain an uninitialized value (equivalent to null)?

I have a class which might have a DateTime property value set or not. I was thinking of initializing the property holder to DateTime.MinValue, which then could easily be checked.

I've been searching a lot but couldn't find a solution.
I guess this is a quite common question, how do you do that?

Ola Ström
  • 4,136
  • 5
  • 22
  • 41
Mats
  • 14,902
  • 33
  • 78
  • 110

16 Answers16

500

For normal DateTimes, if you don't initialize them at all then they will match DateTime.MinValue, because it is a value type rather than a reference type.

You can also use a nullable DateTime, like this:

DateTime? MyNullableDate;

Or the longer form:

Nullable<DateTime> MyNullableDate;

And, finally, there's a built in way to reference the default of any type. This returns null for reference types, but for our DateTime example it will return the same as DateTime.MinValue:

default(DateTime)

or, in more recent versions of C#,

default
Dan
  • 7,286
  • 6
  • 49
  • 114
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • 9
    It would greatly help if you provide an example of how to use it. How do you assign the DateTime in the database, which could be DBNull, to the nullable DateTime? – kirk.burleson Aug 13 '10 at 13:29
  • 9
    It's also good to note that when you DO initialize them and with null, they are assigned `DateTime.MinValue` as well – Jeff LaFay May 21 '13 at 16:22
  • 2
    @kirk.burleson that looks like a separate question. – CompuChip Jul 26 '16 at 09:47
  • you'll need `MyNullableDate=date;` to set it, `MyDate = MyNullableDate.Value;` to read from it, and `if(MyNullableDate.HasValue)` to check if it is null – satibel Dec 22 '16 at 11:06
  • To clarify the answer's "finally" a bit - the default of Nullable (DateTime?) is null, because Nullable creates a reference type. – ryanwebjackson Sep 14 '17 at 15:41
97

If you're using .NET 2.0 (or later) you can use the nullable type:

DateTime? dt = null;

or

Nullable<DateTime> dt = null;

then later:

dt = new DateTime();

And you can check the value with:

if (dt.HasValue)
{
  // Do something with dt.Value
}

Or you can use it like:

DateTime dt2 = dt ?? DateTime.MinValue;

You can read more here:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

Mark Ingram
  • 71,849
  • 51
  • 176
  • 230
45

Following way works as well

myClass.PublishDate = toPublish ? DateTime.Now : (DateTime?)null;

Please note that property PublishDate should be DateTime?

Iman
  • 17,932
  • 6
  • 80
  • 90
Aleksei
  • 1,107
  • 9
  • 13
41

DateTime? MyDateTime{get;set;}

MyDateTime = (dr["f1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)dr["f1"]);
Iman
  • 17,932
  • 6
  • 80
  • 90
14

I'd consider using a nullable types.

DateTime? myDate instead of DateTime myDate.

David Mohundro
  • 11,922
  • 5
  • 40
  • 44
8

You can set the DateTime to Nullable. By default DateTime is not nullable. You can make it nullable in a couple of ways. Using a question mark after the type DateTime? myTime or using the generic style Nullable.

DateTime? nullDate = null;

or

DateTime? nullDate;
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
user29958
  • 81
  • 1
8

It is worth pointing out that, while a DateTime variable cannot be null, it still can be compared to null without a compiler error:

DateTime date;
...
if(date == null) // <-- will never be 'true'
  ...
uncoder
  • 1,818
  • 1
  • 17
  • 20
6

You can use a nullable class.

DateTime? date = new DateTime?();
Aaron Smith
  • 3,332
  • 4
  • 29
  • 25
  • It's probably worth noting this will give you different behavior than instantiating a non-nullable `DateTime`. As previously mentioned, `new DateTime()` will effectively give you `DateTime.Min` whereas `new DateTime?()` will result in null. – Vitoc Aug 02 '19 at 15:16
6

You can use a nullable DateTime for this.

Nullable<DateTime> myDateTime;

or the same thing written like this:

DateTime? myDateTime;
Patrik Svensson
  • 13,536
  • 8
  • 56
  • 77
5

I always set the time to DateTime.MinValue. This way I do not get any NullErrorException and I can compare it to a date that I know isn't set.

Patrick Desjardins
  • 136,852
  • 88
  • 292
  • 341
  • 8
    That means you can't tell the difference between "I really need a DateTime here" and "It's optional" - Nullable is a much better solution, IMO. – Jon Skeet Oct 21 '08 at 13:01
  • ? I really do not get your comment. Yeah I know when the DateTime is so far aways of reality is like if it was null... – Patrick Desjardins Oct 21 '08 at 13:03
  • I am just suggesting an other solution. Instead of repeating what have been suggested already 10 times here. – Patrick Desjardins Oct 21 '08 at 13:04
  • I mean that your type system can't indicate the optional nature of the value. – Jon Skeet Oct 21 '08 at 13:09
  • 2
    It is convenient, but I view DateTime.MinValue as a value, not a special case condition. It can only lead to problems down the line. I'd go with Nullable. – spoulson Oct 21 '08 at 13:13
  • Never got any problem since 2 years with this system. – Patrick Desjardins Oct 21 '08 at 13:18
  • There are any number of bad designs which won't always cause problems - but shouldn't be recommended anyway. I could come along and say that I make all members of all types public, and haven't had any problems - would that be good advice? – Jon Skeet Oct 21 '08 at 13:22
  • 3
    I think you miss something about my answer, Spoulson wrote something and I was answering. About public members, well it's not the same and you know it. it's like String.Empty or null. You can do both, not because String.Empty is better that null is wrong. What ever. – Patrick Desjardins Oct 23 '08 at 17:22
  • 1
    I'm with Daok on this. It might not be the "by the book" approach but it's better than getting a NullReferenceException or dealing with the cumbersome Nullable type. Besides, how many applications are out there that actually need to reference the date January 1, 1 A.D.? – Jacobs Data Solutions Mar 29 '10 at 18:15
4

Just be warned - When using a Nullable its obviously no longer a 'pure' datetime object, as such you cannot access the DateTime members directly. I'll try and explain.

By using Nullable<> you're basically wrapping DateTime in a container (thank you generics) of which is nullable - obviously its purpose. This container has its own properties which you can call that will provide access to the aforementioned DateTime object; after using the correct property - in this case Nullable.Value - you then have access to the standard DateTime members, properties etc.

So - now the issue comes to mind as to the best way to access the DateTime object. There are a few ways, number 1 is by FAR the best and 2 is "dude why".

  1. Using the Nullable.Value property,

    DateTime date = myNullableObject.Value.ToUniversalTime(); //Works

    DateTime date = myNullableObject.ToUniversalTime(); //Not a datetime object, fails

  2. Converting the nullable object to datetime using Convert.ToDateTime(),

    DateTime date = Convert.ToDateTime(myNullableObject).ToUniversalTime(); //works but why...

Although the answer is well documented at this point, I believe the usage of Nullable was probably worth posting about. Sorry if you disagree.

edit: Removed a third option as it was a bit overly specific and case dependent.

Gabe
  • 570
  • 1
  • 4
  • 15
2

Although everyone has already given you the answer , I'll mention a way which makes it easy to pass a datetime into a function

[ERROR:cannot convert system.datetime? to system.datetime]

DateTime? dt = null;
DateTime dte = Convert.ToDateTime(dt);

Now you may pass dte inside the function without any issues.

No Holidays
  • 105
  • 10
1

If you are, sometimes, expecting null you could use something like this:

var orderResults = Repository.GetOrders(id, (DateTime?)model.DateFrom, (DateTime?)model.DateTo)

In your repository use null-able datetime.

public Orders[] GetOrders(string id, DateTime? dateFrom, DateTime? dateTo){...}
DarkoM
  • 335
  • 4
  • 5
1

I had the same problem as I had to give Null as a parameter for DateTime while performing Unit test for Throws ArgumentNullException.It worked in my case using the following option:

Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null));
Kiril Dobrev
  • 839
  • 1
  • 8
  • 12
0

Given the nature of a date/time data type it cannot contain a null value, i.e. it needs to contain a value, it cannot be blank or contain nothing. If you mark a date/time variable as nullable then only can you assign a null value to it. So what you are looking to do is one of two things (there might be more but I can only think of two):

  • Assign a minimum date/time value to your variable if you don't have a value for it. You can assign a maximum date/time value as well - whichever way suits you. Just make sure that you are consistent site-wide when checking your date/time values. Decide on using min or max and stick with it.

  • Mark your date/time variable as nullable. This way you can set your date/time variable to null if you don't have a variable to it.

Let me demonstrate my first point using an example. The DateTime variable type cannot be set to null, it needs a value, in this case I am going to set it to the DateTime's minimum value if there is no value.

My scenario is that I have a BlogPost class. It has many different fields/properties but I chose only to use two for this example. DatePublished is when the post was published to the website and has to contain a date/time value. DateModified is when a post is modified, so it doesn't have to contain a value, but can contain a value.

public class BlogPost : Entity
{
     public DateTime DateModified { get; set; }

     public DateTime DatePublished { get; set; }
}

Using ADO.NET to get the data from the database (assign DateTime.MinValue is there is no value):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? DateTime.MinValue : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

You can accomplish my second point by marking the DateModified field as nullable. Now you can set it to null if there is no value for it:

public DateTime? DateModified { get; set; }

Using ADO.NET to get the data from the database, it will look a bit different to the way it was done above (assigning null instead of DateTime.MinValue):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? (DateTime?)null : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

I hope this helps to clear up any confusion. Given that my response is about 8 years later you are probably an expert C# programmer by now :)

Brendan Vogt
  • 25,678
  • 37
  • 146
  • 234
0

The question itself answers it the proper way. "How do you deal with datetime if it is null?" and questioner gives the answer at the end with DateTime.MinValue. My thought is that questioner's approach should be the way with little change. I would recommend using DateTime.MaxValue to compare since it wont happen until 12/31/9999. If true then show field as something else other than a date. Here is the example;

 DateNotified = DBNull.Value.Equals(reader["DateNotified"])? Convert.ToDateTime(reader["DateNotified"]): DateTime.MaxValue

and on the front end if it is Grid you are using then;

columns.Add(col => col.DateNotified).Css("text-right").Titled("Date Notified").RenderValueAs(c => c.DateNotified.ToString("MM/dd/yyyy").Equals(DateTime.MaxValue) ? "":c.DateNotified.ToString("MM/dd/yyyy"));

or if a simple view then

@Model.DateNotified.ToString("MM/dd/yyyy").Equals(DateTime.MaxValue) ? "":Model.DateNotified.ToString("MM/dd/yyyy")
esenkaya
  • 99
  • 4