276

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

Edward Tanguay
  • 189,012
  • 314
  • 712
  • 1,047
  • 3
    Hello, would you mind reviewing the accepted and current answers? A more relevant to-day answer might be more correct. – iuliu.net May 25 '17 at 07:19

21 Answers21

413
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.

Update: as recommended in the comments, extension method:

public static string ToString(this DateTime? dt, string format)
    => dt == null ? "n/a" : ((DateTime)dt).ToString(format);

And starting in C# 6, you can use the null-conditional operator to simplify the code even more. The expression below will return null if the DateTime? is null.

dt2?.ToString("yyyy-MM-dd hh:mm:ss")
Jeff B
  • 8,572
  • 17
  • 61
  • 140
Blake Pettersson
  • 8,927
  • 3
  • 27
  • 36
85

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
  • 12,312
  • 20
  • 59
  • 78
40

You guys are over engineering this all and making it way more complicated than it really is. Important thing, stop using ToString and start using string formatting like string.Format or methods that support string formatting like Console.WriteLine. Here is the preferred solution to this question. This is also the safest.

Update:

I update the examples with up to date methods of today's C# compiler. conditional operators & string interpolation

DateTime? dt1 = DateTime.Now;
DateTime? dt2 = null;

Console.WriteLine("'{0:yyyy-MM-dd hh:mm:ss}'", dt1);
Console.WriteLine("'{0:yyyy-MM-dd hh:mm:ss}'", dt2);
// New C# 6 conditional operators (makes using .ToString safer if you must use it)
// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators
Console.WriteLine(dt1?.ToString("yyyy-MM-dd hh:mm:ss"));
Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss"));
// New C# 6 string interpolation
// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated
Console.WriteLine($"'{dt1:yyyy-MM-dd hh:mm:ss}'");
Console.WriteLine($"'{dt2:yyyy-MM-dd hh:mm:ss}'");

Output: (I put single quotes in it so you can see that it comes back as a empty string when null)

'2019-04-09 08:01:39'
''
2019-04-09 08:01:39

'2019-04-09 08:01:39'
''
Community
  • 1
  • 1
John C
  • 1,761
  • 2
  • 20
  • 30
  • The 2nd option is the superior choice. String.Format() has to call .ToString() anyways and then do complicated formatting. https://stackoverflow.com/questions/10400142/string-format-vs-tostring – Chris ten Den Feb 05 '21 at 20:44
  • @ChristenDen that's not always the case. That was only introduces in recent updates to C#. And... most of the time when you are formatting a string for display/logging purposes you are using more than one argument to build the string. – John C Feb 22 '21 at 02:13
37

C# 6.0 baby:

dt2?.ToString("dd/MM/yyyy");

iuliu.net
  • 6,666
  • 6
  • 46
  • 69
  • 2
    I would suggest the following version so that this answer is equivalent to the existing accepted answer for C# 6.0. `Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");` – Can Bud Sep 26 '17 at 14:25
32

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 source.Value.ToString(format);
    }
    else {
      return String.IsNullOrEmpty(defaultValue) ?  String.Empty : defaultValue;
    }
  }

  public static string ToStringOrDefault(this DateTime? source, string format) {
       return 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'
surfen
  • 4,644
  • 3
  • 34
  • 46
David Glenn
  • 24,412
  • 19
  • 74
  • 94
16

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
  • 40,310
  • 20
  • 83
  • 102
8

Seeing that you actually want to provide the format I'd suggest to add the IFormattable interface to Smalls extension method like so, that way you don't have the nasty string format concatenation.

public static string ToString<T>(this T? variable, string format, string nullValue = null)
where T: struct, IFormattable
{
  return (variable.HasValue) 
         ? variable.Value.ToString(format, null) 
         : nullValue;          //variable was null so return this value instead   
}
Peter Gluck
  • 8,168
  • 1
  • 38
  • 37
ElmarG
  • 81
  • 1
  • 2
7

What about something as easy as this:

String.Format("{0:dd/MM/yyyy}", d2)
Max Brown
  • 79
  • 1
  • 4
6

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?

H H
  • 263,252
  • 30
  • 330
  • 514
6

Even a better solution in C# 6.0:

DateTime? birthdate;

birthdate?.ToString("dd/MM/yyyy");
Mohammed Noureldin
  • 14,913
  • 17
  • 70
  • 99
6

RAZOR syntax:

@(myNullableDateTime?.ToString("yyyy-MM-dd") ?? String.Empty)
wut
  • 328
  • 1
  • 7
  • 19
5

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
  • 1,434
  • 1
  • 19
  • 19
4

Shortest answer

$"{dt:yyyy-MM-dd hh:mm:ss}"

Tests

DateTime dt1 = DateTime.Now;
Console.Write("Test 1: ");
Console.WriteLine($"{dt1:yyyy-MM-dd hh:mm:ss}"); //works

DateTime? dt2 = DateTime.Now;
Console.Write("Test 2: ");
Console.WriteLine($"{dt2:yyyy-MM-dd hh:mm:ss}"); //Works

DateTime? dt3 = null;
Console.Write("Test 3: ");
Console.WriteLine($"{dt3:yyyy-MM-dd hh:mm:ss}"); //Works - Returns empty string

Output
Test 1: 2017-08-03 12:38:57
Test 2: 2017-08-03 12:38:57
Test 3: 
drobertson
  • 1,548
  • 3
  • 14
  • 25
2

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
  • 2,957
  • 3
  • 25
  • 46
  • 1
    The behaviour with ToString("yy...") _is_ defined if the instance is null, because GetValueOrDefault() will return DateTime.MinValue – Lucas Dec 02 '09 at 14:23
2

Here is Blake's excellent answer as an extension method. Add this to your project and the calls in the question will work as expected.
Meaning it is used like MyNullableDateTime.ToString("dd/MM/yyyy"), with the same output as MyDateTime.ToString("dd/MM/yyyy"), except that the value will be "N/A" if the DateTime is null.

public static string ToString(this DateTime? date, string format)
{
    return date != null ? date.Value.ToString(format) : "N/A";
}
Sinjai
  • 1,085
  • 1
  • 15
  • 34
1

IFormattable also includes a format provider that can be used, it allows both format of IFormatProvider to be null in dotnet 4.0 this would be

/// <summary>
/// Extentionclass for a nullable structs
/// </summary>
public static class NullableStructExtensions {

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <param name="provider">The format provider 
    /// If <c>null</c> the default provider is used</param>
    /// <param name="defaultValue">The string to show when the source is <c>null</c>. 
    /// If <c>null</c> an empty string is returned</param>
    /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, string format = null, 
                                     IFormatProvider provider = null, 
                                     string defaultValue = null) 
                                     where T : struct, IFormattable {
        return source.HasValue
                   ? source.Value.ToString(format, provider)
                   : (String.IsNullOrEmpty(defaultValue) ? String.Empty : defaultValue);
    }
}

using together with named parameters you can do:

dt2.ToString(defaultValue: "n/a");

In older versions of dotnet you get a lot of overloads

/// <summary>
/// Extentionclass for a nullable structs
/// </summary>
public static class NullableStructExtensions {

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <param name="provider">The format provider 
    /// If <c>null</c> the default provider is used</param>
    /// <param name="defaultValue">The string to show when the source is <c>null</c>. 
    /// If <c>null</c> an empty string is returned</param>
    /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, string format, 
                                     IFormatProvider provider, string defaultValue) 
                                     where T : struct, IFormattable {
        return source.HasValue
                   ? source.Value.ToString(format, provider)
                   : (String.IsNullOrEmpty(defaultValue) ? String.Empty : defaultValue);
    }

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <param name="defaultValue">The string to show when the source is null. If <c>null</c> an empty string is returned</param>
    /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, string format, string defaultValue) 
                                     where T : struct, IFormattable {
        return ToString(source, format, null, defaultValue);
    }

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <param name="provider">The format provider (if <c>null</c> the default provider is used)</param>
    /// <returns>The formatted string or an empty string if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, string format, IFormatProvider provider)
                                     where T : struct, IFormattable {
        return ToString(source, format, provider, null);
    }

    /// <summary>
    /// Formats a nullable struct or returns an empty string
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <returns>The formatted string or an empty string if the source is null</returns>
    public static string ToString<T>(this T? source, string format)
                                     where T : struct, IFormattable {
        return ToString(source, format, null, null);
    }

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="provider">The format provider (if <c>null</c> the default provider is used)</param>
    /// <param name="defaultValue">The string to show when the source is <c>null</c>. If <c>null</c> an empty string is returned</param>
    /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, IFormatProvider provider, string defaultValue)
                                     where T : struct, IFormattable {
        return ToString(source, null, provider, defaultValue);
    }

    /// <summary>
    /// Formats a nullable struct or returns an empty string
    /// </summary>
    /// <param name="source"></param>
    /// <param name="provider">The format provider (if <c>null</c> the default provider is used)</param>
    /// <returns>The formatted string or an empty string if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, IFormatProvider provider)
                                     where T : struct, IFormattable {
        return ToString(source, null, provider, null);
    }

    /// <summary>
    /// Formats a nullable struct or returns an empty string
    /// </summary>
    /// <param name="source"></param>
    /// <returns>The formatted string or an empty string if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source) 
                                     where T : struct, IFormattable {
        return ToString(source, null, null, null);
    }
}
Kiquenet
  • 14,494
  • 35
  • 148
  • 243
JeroenH
  • 11
  • 1
1

I like this option:

Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss") ?? "n/a");
Pang
  • 9,564
  • 146
  • 81
  • 122
Martin
  • 21
  • 5
0

Simple generic extensions

public static class Extensions
{

    /// <summary>
    /// Generic method for format nullable values
    /// </summary>
    /// <returns>Formated value or defaultValue</returns>
    public static string ToString<T>(this Nullable<T> nullable, string format, string defaultValue = null) where T : struct
    {
        if (nullable.HasValue)
        {
            return String.Format("{0:" + format + "}", nullable.Value);
        }

        return defaultValue;
    }
}
Andzej Maciusovic
  • 4,306
  • 1
  • 29
  • 40
0

s.DateTime != null ? ((DateTime)s.SendDateTime).ToString("HH:mm:ss") : null

  • 2
    On Stack Overflow, the **how** is important, but a great part of the quality level of the site comes from the fact that people go to great lengths to explain the **why**. While a _code-only_ answer get the person who asked the question past whatever hurdle they might be facing, it doesn't do them or future visitors much good in the long run. See [Is there any benefit in code-only answers?](https://meta.stackexchange.com/a/148274/183937) – Steve May 09 '22 at 07:06
-2

Maybe it is a late answer but may help anyone else.

Simple is:

nullabledatevariable.Value.Date.ToString("d")

or just use any format rather than "d".

Best

Waleed
  • 49
  • 1
  • 1
  • 7
-2

you can use simple line:

dt2.ToString("d MMM yyyy") ?? ""
Andy
  • 49,085
  • 60
  • 166
  • 233
Daniel Heo
  • 27
  • 3