Wie kann ich mit ToString () eine nullfähige DateTime formatieren?

226

Wie kann ich die nullfähige DateTime dt2 in eine formatierte Zeichenfolge konvertieren ?

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:

Keine Überladung der Methode ToString erfordert ein Argument

Edward Tanguay
quelle
3
Hallo, würde es Ihnen etwas ausmachen, die akzeptierten und aktuellen Antworten zu überprüfen? Eine relevantere heutige Antwort könnte korrekter sein.
iuliu.net

Antworten:

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

BEARBEITEN: Wie in anderen Kommentaren angegeben, überprüfen Sie, ob ein Wert ungleich Null vorhanden ist.

Update: wie in den Kommentaren empfohlen, Erweiterungsmethode:

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

Ab C # 6 können Sie den nullbedingten Operator verwenden , um den Code noch weiter zu vereinfachen. Der folgende Ausdruck gibt null zurück, wenn der DateTime?Wert null ist.

dt2?.ToString("yyyy-MM-dd hh:mm:ss")
Blake Pettersson
quelle
26
Das sieht so aus, als würde es mich um eine Erweiterungsmethode bitten.
David Glenn
42
.Wert ist der Schlüssel
stuartdotnet
@ David nicht, dass die Aufgabe nicht trivial ist ... stackoverflow.com/a/44683673/5043056
Sinjai
3
Bist du bereit dafür ... dt? .ToString ("TT / MMM / JJJJ")? "" Große Vorteile von C # 6
Tom McDonough
Fehler CS0029: Typ 'Zeichenfolge' kann nicht implizit in 'System.DateTime?' Konvertiert werden. (CS0029). .Net Core 2.0
Oracular Man
80

Probieren Sie dies für die Größe an:

Das tatsächliche dateTime-Objekt, das Sie formatieren möchten, befindet sich in der Eigenschaft dt.Value und nicht im Objekt dt2.

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

Ihr seid damit fertig, das alles zu konstruieren und es viel komplizierter zu machen, als es wirklich ist. Wichtig ist, dass Sie ToString nicht mehr verwenden und die Formatierung von Zeichenfolgen wie string.Format oder Methoden, die die Formatierung von Zeichenfolgen unterstützen, wie Console.WriteLine verwenden. Hier ist die bevorzugte Lösung für diese Frage. Dies ist auch am sichersten.

Aktualisieren:

Ich aktualisiere die Beispiele mit aktuellen Methoden des heutigen C # -Compilers. Bedingte Operatoren & 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://docs.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://docs.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}'");

Ausgabe: (Ich habe einfache Anführungszeichen eingefügt, damit Sie sehen können, dass es als leere Zeichenfolge zurückkommt, wenn es null ist.)

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

'2019-04-09 08:01:39'
''
John C.
quelle
30

Wie andere angegeben haben, müssen Sie vor dem Aufrufen von ToString nach null suchen. Um jedoch zu vermeiden, dass Sie sich wiederholen, können Sie eine Erweiterungsmethode erstellen, die dies tut, etwa:

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);
  }

}

Welches kann aufgerufen werden wie:

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 Glenn
quelle
28

C # 6.0 Baby:

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

iuliu.net
quelle
2
Ich würde die folgende Version vorschlagen, damit diese Antwort der vorhandenen akzeptierten Antwort für C # 6.0 entspricht. Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
Can Bud
15

Das Problem bei der Formulierung einer Antwort auf diese Frage besteht darin, dass Sie die gewünschte Ausgabe nicht angeben, wenn die nullfähige Datumszeit keinen Wert hat. Der folgende Code wird DateTime.MinValuein einem solchen Fall ausgegeben und löst im Gegensatz zur derzeit akzeptierten Antwort keine Ausnahme aus.

dt2.GetValueOrDefault().ToString(format);
Matt Howells
quelle
7

Da Sie tatsächlich das Format bereitstellen möchten, würde ich vorschlagen, die IFormattable-Schnittstelle wie folgt zur Smalls-Erweiterungsmethode hinzuzufügen, damit Sie nicht die unangenehme Verkettung des Zeichenfolgenformats haben.

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   
}
ElmarG
quelle
6

Was ist mit so etwas Einfachem:

String.Format("{0:dd/MM/yyyy}", d2)
Max Brown
quelle
5

Sie können verwenden dt2.Value.ToString("format"), aber das erfordert natürlich, dass dt2! = Null ist, und das negiert die Verwendung eines nullbaren Typs an erster Stelle.

Hier gibt es mehrere Lösungen, aber die große Frage ist: Wie möchten Sie ein nullDatum formatieren ?

Henk Holterman
quelle
5

Hier ist ein allgemeinerer Ansatz. Auf diese Weise können Sie einen beliebigen nullbaren Werttyp formatieren. Ich habe die zweite Methode eingefügt, um das Überschreiben des Standardzeichenfolgenwerts zu ermöglichen, anstatt den Standardwert für den Werttyp zu verwenden.

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
quelle
4

Kürzeste Antwort

$"{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
quelle
4

Noch eine bessere Lösung in C # 6.0:

DateTime? birthdate;

birthdate?.ToString("dd/MM/yyyy");
Mohammed Noureldin
quelle
4

RAZOR-Syntax:

@(myNullableDateTime?.ToString("yyyy-MM-dd") ?? String.Empty)
wut
quelle
2

Ich denke, Sie müssen die GetValueOrDefault-Methode verwenden. Das Verhalten mit ToString ("yy ...") ist nicht definiert, wenn die Instanz null ist.

dt2.GetValueOrDefault().ToString("yyy...");
Martin
quelle
1
Das Verhalten mit ToString ("yy ...") wird definiert, wenn die Instanz null ist, da GetValueOrDefault () DateTime.MinValue
Lucas
2

Hier ist Blakes ausgezeichnete Antwort als Erweiterungsmethode. Fügen Sie dies Ihrem Projekt hinzu, und die Aufrufe in der Frage funktionieren wie erwartet. Dies bedeutet , dass
es wie MyNullableDateTime.ToString("dd/MM/yyyy")mit der gleichen Ausgabe wie verwendet wird MyDateTime.ToString("dd/MM/yyyy"), außer dass der Wert "N/A"lautet , wenn DateTime null ist.

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

IFormattable enthält auch einen Formatanbieter, der verwendet werden kann. Dadurch können beide Formate von IFormatProvider in Dotnet 4.0 null sein

/// <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);
    }
}

zusammen mit benannten Parametern können Sie Folgendes tun:

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

In älteren Dotnet-Versionen kommt es zu vielen Überlastungen

/// <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);
    }
}
JeroenH
quelle
1

Ich mag diese Option:

Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss") ?? "n/a");
Martin
quelle
0

Einfache generische Erweiterungen

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
quelle
-2

Vielleicht ist es eine späte Antwort, kann aber jedem anderen helfen.

Einfach ist:

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

oder verwenden Sie einfach ein beliebiges Format anstelle von "d".

Beste

Waleed
quelle
1
Dies tritt auf, wenn nullabledatevariable.Value null ist.
John C
-2

Sie können einfache Linie verwenden:

dt2.ToString("d MMM yyyy") ?? ""
Daniel Heo
quelle