views:

854

answers:

7

How can I convert the nullable DateTime dt2 to a formatted string?

DateTime dt = DateTime.Now;
Console.WriteLine(dt.ToString("yyyy-MM-dd hh:mm:ss")); //works

DateTime? dt2 = DateTime.Now;
Console.WriteLine(dt2.ToString("yyyy-MM-dd hh:mm:ss")); //gives following error:

no overload to method ToString takes one argument

+7  A: 
Console.WriteLine(dt2 != null ? dt2.Value.ToString("yyyy-MM-dd hh:mm:ss") : "n/a");

EDIT: As stated in other comments, check that there is a non-null value.

Blake Pettersson
This will throw an exception if dt2 has no value.
Matt Howells
This will _still_ throw an exception if dt2 has no value - as opposed to being null.
Matt Howells
This looks like it's begging for an extension method to me.
David G
@Matt - What is the difference between "no value" and null with a nullable type? MSDN states "HasValue is of type bool. It is set to true when the variable contains a non-null value."This answer doesn't seem to agree with you either: http://stackoverflow.com/questions/676078/which-is-preferred-nullable-hasvalue-or-nullable-null
Blake Pettersson
The relevant link on MSDN: http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx
Blake Pettersson
+4  A: 

You can use dt2.Value.ToString("format"), but of course that requires that dt2 != null, and that negates th use of a nullable type in the first place.

There are several solutions here, but the big question is: How do you want to format a null date?

Henk Holterman
+8  A: 

Try this on for size:

The actual dateTime object your looking to format is in the dt.Value property, and not on the dt2 object itself.

DateTime? dt2 = DateTime.Now;
 Console.WriteLine(dt2.HasValue ? dt2.Value.ToString("yyyy-MM-dd hh:mm:ss") : "[N/A]");
Russ
+1  A: 

The problem with formulating an answer to this question is that you do not specify the desired output when the nullable datetime has no value. The following code will output DateTime.MinValue in such a case, and unlike the currently accepted answer, will not throw an exception.

dt2.GetValueOrDefault().ToString(format);
Matt Howells
+1  A: 

I think you have to use the GetValueOrDefault-Methode. The behaviour with ToString("yy...") is not defined if the instance is null.

dt2.GetValueOrDefault().ToString("yyy...");
martin
The behaviour with ToString("yy...") _is_ defined if the instance is null, because GetValueOrDefault() will return DateTime.MinValue
Lucas
+1  A: 

As others have stated you need to check for null before invoking ToString but to avoid repeating yourself you could create an extension method that does that, something like:

public static class DateTimeExtensions {

  public static string ToStringOrDefault(this DateTime? source, string format, string defaultValue) {
    if (source != null) {
      return DateTime.Value.ToString(format);
    }
    else {
      return String.IsNullOrEmpty(defaultValue) ? defaultValue : String.Empty;
    }
  }

  public static string ToStringOrDefault(this DateTime? source, string format) {
     ToStringOrDefault(source, format, null);
  }

}

Which can be invoked like:

DateTime? dt = DateTime.Now;
dt.ToStringOrDefault("yyyy-MM-dd hh:mm:ss");  
dt.ToStringOrDefault("yyyy-MM-dd hh:mm:ss", "n/a");
dt = null;
dt.ToStringOrDefault("yyyy-MM-dd hh:mm:ss", "n/a")  //outputs 'n/a'
David G
A: 

Here is a more generic approach. This will allow you to string format any nullable value type. I have included the second method to allow overriding the default string value instead of using the default value for the value type.

public static class ExtensionMethods
{
    public static string ToString<T>(this Nullable<T> nullable, string format) where T : struct
    {
        return String.Format("{0:" + format + "}", nullable.GetValueOrDefault());
    }

    public static string ToString<T>(this Nullable<T> nullable, string format, string defaultValue) where T : struct
    {
        if (nullable.HasValue) {
            return String.Format("{0:" + format + "}", nullable.Value);
        }

        return defaultValue;
    }
}
Schmalls