2009-12-02 15 views
173

Come posso convertire il valore nulla DateTime dt2 in una stringa formattata?Come posso formattare un DateTime nullable con ToString()?

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: 

sovraccarico al metodo ToString prende un argomento

+2

Ciao, ti dispiacerebbe rivedere le risposte accettati e attuali? Una risposta più attuale potrebbe essere più corretta. –

risposta

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

EDIT: Come detto in altri commenti, controllare che non v'è un valore non nullo.

Update: come raccomandato nei commenti, metodo di estensione:

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

E a partire dal C# 6, è possibile utilizzare il null-conditional operator per semplificare il codice ancora di più. L'espressione seguente restituirà null se DateTime? è nullo.

dt2?.ToString("yyyy-MM-dd hh:mm:ss") 
+24

Sembra che mi stia chiedendo un metodo di estensione. –

+33

.Value è la chiave – stuartdotnet

+1

Yessss! Magia! Questo mi ha sempre infastidito - grazie per una buona soluzione! – wubblyjuggly

5

È possibile utilizzare dt2.Value.ToString("format"), ma, naturalmente, che richiede che dt2! = Null, e che nega l'uso esimo di un tipo nullable in primo luogo.

Ci sono diverse soluzioni qui, ma la grande domanda è: come si desidera formattare una data null?

70

Prova questo per il formato:

Il dateTime attuale oggetto la vostra ricerca per formattare è nella proprietà dt.Value, e non sull'oggetto dt2 stesso.

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

Il problema di formulare una risposta a questa domanda è che non si specifica l'output desiderato quando il datetime nullable non ha alcun valore. Il codice seguente emetterà DateTime.MinValue in tal caso e, a differenza della risposta attualmente accettata, non genererà un'eccezione.

dt2.GetValueOrDefault().ToString(format); 
+8

L'output di MinValue probabilmente non sarà il comportamento desiderato. – jmoreno

2

Penso che sia necessario utilizzare il metodo GetValueOrDefault. Il comportamento con ToString ("yy ...") non è definito se l'istanza è nullo.

dt2.GetValueOrDefault().ToString("yyy..."); 
+1

Il comportamento con ToString ("yy ...") _è_ definito se l'istanza è nullo, perché GetValueOrDefault() restituirà DateTime.MinValue – Lucas

31

Come altri hanno detto è necessario controllare per nulla prima di richiamare ToString ma per evitare di ripetere se stessi è possibile creare un metodo di estensione che lo fa, qualcosa di simile:

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

} 

Che può essere invocato come :

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' 
5

Ecco un approccio più generico. Ciò ti consentirà di formattare in formato stringa qualsiasi tipo di valore nullable. Ho incluso il secondo metodo per consentire l'override del valore di stringa predefinito anziché utilizzare il valore predefinito per il tipo di valore.

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

Vedendo che in realtà si vuole fornire il formato suggerirei aggiungere l'interfaccia IFormattable al metodo di estensione Smalls in questo modo, in questo modo non si ha la brutta concatenazione di formato di stringa.

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 
} 
1

IFormattable include anche un provider di formato che può essere usato, permette sia in formato di IFormatProvider ad essere nullo in dotnet 4.0 questo sarebbe

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

usando insieme con i parametri denominati si può fare:

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

Nelle versioni precedenti di dotnet si ottiene un sacco di sovraccarichi

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

Voi ragazzi sono più di ingegneria tutto questo e che lo rende molto più complicato di quanto non sia in realtà. Importante, smetti di usare ToString e inizia a utilizzare la formattazione di stringhe come string.Format o metodi che supportano la formattazione di stringhe come Console.WriteLine. Ecco la soluzione preferita a questa domanda. Questo è anche il più sicuro.

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

uscita: (metto le virgolette singole in modo da poter vedere che ritorna come una stringa vuota quando null)

'2014-01-22 09:41:32' 
'' 
+3

Bello e semplice –

0

semplici estensioni generiche

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

C# 6.0 baby:

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

+1

Suggerirei la seguente versione in modo che questa risposta sia equivalente alla risposta accettata esistente per C# 6.0. 'Console.WriteLine (dt2? .ToString (" aaaa-MM-gg hh: mm: ss "??" n/a ");' –

-1

Forse è una risposta tardiva, ma può aiutare qualcun altro.

semplice è:

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

o semplicemente utilizzare qualsiasi formato, piuttosto che "d".

Miglior

+0

Questo errore quando nullabledatevariable.Value è nullo. –

-1

è possibile utilizzare semplice linea:

dt2.ToString("d MMM yyyy") ?? "" 
+0

Questo errore quando dt2 è nullo. –

1

mi piace questa opzione:

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

Che dire qualcosa di semplice come questo:

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

Qui è Blake's excellent answer come metodo di estensione. Aggiungi questo al tuo progetto e le chiamate nella domanda funzioneranno come previsto. Poiché viene utilizzato come MyNullableDateTime.ToString("dd/MM/yyyy"), con la stessa uscita di MyDateTime.ToString("dd/MM/yyyy"), ad eccezione del fatto che il valore sarà "N/A" se DateTime è nullo.

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

risposta più breve

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

Test

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: 
0

Ancora una soluzione migliore in C# 6.0: sintassi

DateTime? birthdate; 

birthdate?.ToString("dd/MM/yyyy"); 
0

RAZOR:

@(myNullableDateTime?.ToString("yyyy-MM-dd") ?? String.Empty) 
Problemi correlati