53

While converting .NET DateTime (when is default(DateTime)) to SqlDateTime should I always check if the .NET date is between SqlDateTime.MinValue and SqlDateTime.MaxValue [or] Is there a good way to do this.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Sreedhar
  • 29,307
  • 34
  • 118
  • 188

6 Answers6

96

Is it possible that the date could actually be outside that range? Does it come from user input? If the answer to either of these questions is yes, then you should always check - otherwise you're leaving your application prone to error.

You can format your date for inclusion in an SQL statement rather easily:

var sqlFormattedDate = myDateTime.Date.ToString("yyyy-MM-dd HH:mm:ss");
Winston Smith
  • 21,585
  • 10
  • 60
  • 75
  • @Winston: Yes my incoming date can be null sometime. – Sreedhar Feb 03 '10 at 10:26
  • 17
    @Winston: You *should not* format your date as a string for inclusion in a SQL statement. Use parameterised SQL with a strongly-typed parameter instead. – LukeH Feb 03 '10 at 11:33
  • 6
    I agree with luke. What if you were born on the "users" of the month "table", in the year "drop"? (Seriously tho, do what Luke says) – Rob Fonseca-Ensor Feb 03 '10 at 14:16
  • 4
    Rob: Not possible with a .NET DateTime object, as the formatting is directly converted from numeric values. – marknuzz Dec 06 '13 at 00:55
  • @LukeH, what's wrong with doing that? The format looks culture/region-independent, so it might be reliable. (Feel free to let me know if I'm wrong, though.) – Sam Oct 22 '14 at 23:53
  • 2
    @Sam: In addition to the security issue mentioned by Rob above, the `yyyy-MM-dd` format isn't completely culture-independent. More details here: https://sqlblog.org/2009/10/16/bad-habits-to-kick-mis-handling-date-range-queries – LukeH Nov 03 '14 at 13:58
  • @LukeH, thanks! I didn't know that. Regarding the security issue pointed out by Rob, is it really possible for .NET to format a `MM` or `dd` for a `DateTime` as `users` or `table`? – Sam Nov 03 '14 at 21:15
  • @Sam: `var c = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone(); c.DateTimeFormat.TimeSeparator = "';DROP TABLE users;--"; Thread.CurrentThread.CurrentCulture = c; Console.WriteLine("SELECT x FROM y WHERE z = '" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "'");` – LukeH Nov 04 '14 at 11:17
  • 1
    @Sam: I don't know whether similar attacks are possible/likely in the OP's real-world situation; I'd rather just use proper parameterised SQL and avoid the risk altogether. – LukeH Nov 04 '14 at 11:18
  • Use "yyyy-MM-dd HH:mm:ss.fff" to include milliseconds. – richardwhatever Jul 28 '15 at 06:29
2

If you are checking for DBNULL, converting a SQL Datetime to a .NET DateTime should not be a problem. However, you can run into problems converting a .NET DateTime to a valid SQL DateTime.

SQL Server does not recognize dates prior to 1/1/1753. Thats the year England adopted the Gregorian Calendar. Usually checking for DateTime.MinValue is sufficient, but if you suspect that the data could have years before the 18th century, you need to make another check or use a different data type. (I often wonder what Museums use in their databases)

Checking for max date is not really necessary, SQL Server and .NET DateTime both have a max date of 12/31/9999 It may be a valid business rule but it won't cause a problem.

fremis
  • 584
  • 4
  • 4
1

Also please remember resolutions [quantum of time] are different.

http://msdn.microsoft.com/en-us/library/system.data.sqltypes.sqldatetime.aspx

SQL one is 3.33 ms and .net one is 100 ns.

Fakrudeen
  • 5,778
  • 7
  • 44
  • 70
1

on my quest to do this with entitie, i stumbled over here, just hitting back to post what i've found out...

when using EF4, "a sql's" datetime column can be filled from .NET's DateTime using BitConverter.

EntitieObj.thetime = BitConverter.GetBytes(DateTime.Now.ToBinary());

also Fakrudeen's link brought me further... thank you.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
womd
  • 3,077
  • 26
  • 20
0

-To compare only the date part, you can do:

var result = db.query($"SELECT * FROM table WHERE date >= '{fromDate.ToString("yyyy-MM-dd")}' and date <= '{toDate.ToString("yyyy-MM-dd"}'");
0
var sqlCommand = new SqlCommand("SELECT * FROM mytable WHERE start_time >= @StartTime");
sqlCommand.Parameters.Add("@StartTime", SqlDbType.DateTime);
sqlCommand.Parameters("@StartTime").Value = MyDateObj;
rsc
  • 10,348
  • 5
  • 39
  • 36
  • 1
    While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. [From Review](/review/low-quality-posts/26240421) – double-beep May 27 '20 at 05:24