‘Stupid’ Question 32: How do you check if the value for a DateTime property is set?
Can time be null? Not unless you say it can
Today I was looking for an alternative way to check if DateTime as been assigned a value or not, if I’m not using a nullable type. I was just curious if this could be done. The thing is, DateTime is a Value type,- so it can’t be null unless you of course make it a nullable type. Value types are stored as the value they are assigned, in contrast to reference types that point to an object - and thus it makes no sense having a value type with the value of null .
A nullable type lets you represent a value type as anything within the set range, or as null. Now, what if you, for whatever reason, don’t want to make a value a nullable type? What you can do is to use the DateTime.MinValue, which is the smallest possible value that a DateTime can have, and also the value an unassigned DateTime has.
I reckon that is makes more sense to make DateTime a nullable type, what do you think? When would be a good time to use DateTime.MinValue?
Comments
I think the best thing you can do is look at the default value of the value type. In case of DateTime this is DateTime.MinValue. So DateTime dateTime = default(DateTime);. It's not a guarantee, but I normally use this to indicate that a value has not yet been set.
I want to note that the "datetime2" column type on SQL Server pre-2012 supports DateTime.MinValue in .NET. I do think that SQL Server 2012 now supports DateTime.MinValue with the default datetime column type, but not sure?
I usually use nullable types for DateTime structs. However, you can use DateTime.MinValue as well. Its really your preference in my opinion. As long as you are consistent with its use I don't think either method is bad.
I either will use a nullable datetime (DateTime? nullDate = null;) or I will default the value MinValue like (DateTime nullDate = DateTime.MinValue;). Both will work, you just have to be consistent! Love your blog, Iris!
Haven't tried that myself, but still - what good is the date 01.01.0001? When would you ever want that in you data. In my opinion, it's bad data...
Do you mean that applies to other valuetypes as well? the default value of Int is 0, and in many cases that will be a valid value...
One advantage of using DateTime.MinValue is that it is a valid value. i.e.if (startDate < DateTime.Now)
will work is startDate is MinValue or a specific date. In fact, if you want the unassigned/default/null value to mean "include all dates" then you'll probably need to do this anyway:if (startDate.IsNull) startDate = DateTimeMinValue; if (EndDate.IsNull) endDate = DateTime.MaxValue;
It depends, right? There are a few ways, given the language of choice. Now in your world, you have chosen C# and typically unless you have declared that the DateTime can be null; the best option is DateTime dt; ... if (dt == DateTime.MinValue) DoSomething(); However, IF dt is declare as a nullable type then if (dt == null || dt == DateTime.MinValue) DoSomething(); In VB.NET you can always revert to the Date helper classes with If IsDate(dt) Then DoSomeThing() End If
Well DateTime is a struct and so called a value type. and its a composition of different value types so making nullable doesn't make sense. Better go with a default value so called DateTime.MinValue. hope this make sense. cheers!!
Just set a date far enough where we would either be all dead or the application would probably be re-written by that time and use it as the default state of the data object. DateTime.MinValue and DateTime.MaxValue does the job as well.
In that case, I'd just check if the DateTime is valid for SQL Server:
public static bool IsValidForSqlServer(this DateTime date)
{
if (date < (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue)
{
return false;
}
if (date > (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue)
{
return false;
}
return true;
}
Use DateTime.MinValue.Subtract(TimeSpan.FromSeconds(1)) to avoid confusing with default(DateTime) :-)
Of course, but my point was not necessarily only when saving to a Database. The DateTime.Minvalue (or MaxValue for that matter), is in 99% of the cases "Invalid data", and hence it might as well be nullable.
Well, I guess it depends on whether you are planning on storing the value or just using it as a range. e.g., For a birthday field, I would definitely use a DateTime? with null meaning "no date given". OTOH, in an input field, for a "display records within the date range", I'd use the value type with MinValue & MaxValue as the defaults, meaning "given me everything since the beginning (until the end) of the records on file"
using DateTime.Min or Max is using "magic values" and giving them more meaning then they are worth. when representing an interval i would just use nullable type rather then Min/Max. more logical to have a null value representing a open interval. using DateTime.MinValue with the db can also get you into invalid types, especially when using smallDateTime. would rather have nullable on the front end, and smalldatetime (nullable) on the db. i think it's more natural to use nullable to signify "no value" than to use MinValue/MaxValue. cases when i see this fit? can't think of one now. anyway, as someone said before, go for any but be consistent.
Yes, as far as I known you can use the default keyword for all value types. Including int, bool, float, etc. To be more precise all types deriving from System.ValueType
DateTime.MinValue (or another low value) can often be better than null in scenarios where you are doing SQL queries that work with the date field. There are many different scenarios where it could apply, and even the use of MaxValue as well. When doing integrations with third parties, it also often better to always return a date than nothing. I do use nullable date objects myself most of the time, but there are some uses for default dates as well in certain scenarios.
Null is by far my preferred route, because datetime.min or max might have you saying worthless info to your db.
I do daily work with a (relatively) legacy MSSQL database and almost every table has a couple of dates in them. They are all nullable and I find that the easiest way to handle them is:
DateTime? dt = null;
var dateValue = dt.GetValueOrDefault(); //great method on all nullables!
//this is now true: dateValue == DateTime.MinValue
GetValueOrDefault() is great for using nullable datetimes (for compatibility) while at the same time easily making sure they have *some* value in the code. I vastly prefer this to storing a magic value in the database.
I usually like my code to be unambiguous. If you want to describe that a variable has no valid value, you should not use one of the type's valid values to describe it. I do not hesitate to use Nullable wherever it makes sense. I do hesitate not to, on the other hand. Before Nullable graced us with its presence, I sometimes saw a pattern where you would "pair" properties. So if you had a property "DateTime CreatedDate", there would also be a "Bool CreatedDateIsNull" or so, which would indicate whether or not CreatedDate had gotten a valid value assigned. I would not dream of using such a pattern today, when Nullable solves this problem in a much clearer way.
Well said. I have too seen this pattern and like nullable much much better!
I tend to avoid nullable types where possible as others consuming the code may be expecting a simple value type and not check for the null.
It is true thatDateTime
is a struct, but under-the-covers it is just aulong
, so making it nullable makes just as much sense as for any other value type.
You can't do this! The resulting value is out of range and throws an exception!
If you're going to make theDateTime
be nullable, then explicitly checking for the null value obscures the intent of being nullable in the first place. Use the.HasValue
property, as that makes the intent more apparent to future developers who may look at the code. Also, use of the null coalescing operator (??
) is very apropriate with nullable data types.
Nullable nullDateTime; or DateTime? nullDateTime = null; Full source..Nullable DateTime Crony
Last modified on 2012-08-26