14

I have two DateTime objects, BirthDate and HireDate. They are correctly formatted as a string and when I pass them through to my data access layer, they need to be parsed into a DateTime object.

DateTime hD = DateTime.Parse(hire);            
DateTime bD = DateTime.Parse(birth);

//incase of a datestring being passed through
dateStringPassed = "7/2/1969";

But sometimes, the strings hire and birth are null or empty "", if the code is run like this, I get a FormatException error from Parsing a empty string. How can I manage empty parses and allow the DateTime, if empty or null, be accepted as DBNull.Value?

I still cannot manage incase the user does not pass through a DateTime string, then the parse crashes my code.

My parameter for birth date is as follows and checks the variable if null, then use DBNull.Value.

GivenPie
  • 1,451
  • 9
  • 36
  • 57

3 Answers3

22

The Parse method can't handle empty strings, but you can use nullable DateTime and do something like this:

DateTime? hD = String.IsNullOrEmpty(hire) ? (DateTime?)null : DateTime.Parse(hire)

But even safer would be using TryParse instead:

DateTime? hD = null;
DateTime.TryParse(hire, out hD);

Then for storing this value, you can test hD.HasValue:

if(hD.HasValue) { /* use hD */ }
else { /* else use DBNull.Value */ }

Since C# 7, you can use shorter syntax for inline out parameters and you can avoid nullable type altogether:

if (DateTime.TryParse(hire, out var hD)) { /* use hD */ }
else { /* use DBNull.Value */ }
Honza Brestan
  • 10,637
  • 2
  • 32
  • 43
  • 1
    I believe you will have to cast the `null` in that ternary operator in order to get that line to compile. Both sides of the `:` need to be of the same type or types that have implicit conversions between them. – Oded Nov 25 '12 at 21:15
  • 1
    And that last line - I don't see how you could cast that so the compiler can accept it. – Oded Nov 25 '12 at 21:20
  • Agreed, tryParse is super useful here to avoid additional if checks and keep code cleaner – Nikki Jun 07 '20 at 18:08
5

You need to use nullable date times - the shortcut syntax would be DateTime? (note the ? at the end).

DateTime? hD = null;
if(!string.IsNullOrWhitespace(hire )) // string.IsNullOrEmpty if on .NET pre 4.0
{
   hD = DateTime.Parse(hire);            
}

You can test for hD.HasValue and if it doesn't use DbNull.Value instead.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • Can you write an example with DateTime bD = DateTime.Parse(birth)? Will using a `?` at the end work also for an `int`? – GivenPie Nov 25 '12 at 21:10
  • @GivenPie - Yes, it would for an `int` and any value type. – Oded Nov 25 '12 at 21:12
  • Hey Oded, I've called the `.HasValue` like this: `.Value = bD.HasValue ? DBNull.Value : (object)bD;` and my debugger is telling me this Parameter has no Default value. What do you think this means? – GivenPie Nov 25 '12 at 22:04
  • You are setting `.Value` to `DBNull.Value` if _there is_ a value and passing `null` if not. You need to flip the two results to `.Value = bD.HasValue ? (object)bD : DBNull.Value;` – Oded Nov 26 '12 at 10:05
1

If you use this method, any thing that is not a correct date will return a DBNull.Value:

/// <summary>
/// Parses a date string and returns
/// a DateTime if it is a valid date,
/// if not returns DBNull.Value
/// </summary>
/// <param name="date">Date string</param>
/// <returns>DateTime or DBNull.Value</returns>
public static object CreateDBDateTime(string date)
{
    DateTime result;
    if (DateTime.TryParse(date, out result))
    {
        return result;
    }
    return DBNull.Value;
}
Jens Granlund
  • 4,950
  • 1
  • 31
  • 31