Come posso formattare un DateTime nullable con ToString ()?


226

Come posso convertire il DateTime dt2 nullable in una stringa formattata?

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:

nessun sovraccarico al metodo ToString accetta un argomento


3
Ciao, ti dispiacerebbe rivedere le risposte accettate e attuali? Una risposta più pertinente potrebbe essere più corretta.
iuliu.net,

Risposte:


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

MODIFICA: Come indicato in altri commenti, verificare che sia presente un valore non nullo.

Aggiornamento: 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 da C # 6, è possibile utilizzare l' operatore null-condizionale per semplificare ulteriormente il codice. L'espressione seguente restituirà null se DateTime?è null.

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

26
Sembra che mi stia chiedendo un metodo di estensione.
David Glenn,

42
.Value è la chiave
stuartdotnet

@ David non che il compito non è banale ... stackoverflow.com/a/44683673/5043056
Sinjai

3
Sei pronto per questo ... dt? .ToString ("dd / MMM / yyyy") ?? "" Grandi vantaggi di C # 6
Tom McDonough,

Errore CS0029: Impossibile convertire in modo implicito il tipo "stringa" in "System.DateTime?" (CS0029). .Net Core 2.0
Oracular Man,

80

Prova questo per dimensioni:

L'oggetto dateTime reale che stai cercando di 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]");

36

Ragazzi, state progettando tutto questo e rendendolo molto più complicato di quanto non sia in realtà. Cosa importante, smetti di usare ToString e inizia a usare 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.

Aggiornare:

Aggiornamento gli esempi con metodi aggiornati del compilatore C # di oggi. operatori condizionali e interpolazione di stringhe

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

Output: (ho inserito virgolette singole in modo da poter vedere che ritorna come stringa vuota quando è null)

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

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

30

Come altri hanno affermato, è necessario verificare la presenza di null prima di richiamare ToString, ma per evitare di ripetersi è possibile creare un metodo di estensione che lo faccia, qualcosa del tipo:

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'

28

C # 6.0 bambino:

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


2
Vorrei suggerire la seguente versione in modo che questa risposta sia equivalente alla risposta accettata esistente per C # 6.0. Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
Can Bud,

15

Il problema con la formulazione di una risposta a questa domanda è che non si specifica l'output desiderato quando il datetime nullable non ha valore. In DateTime.MinValuetal caso, verrà emesso il seguente codice e, diversamente dalla risposta attualmente accettata, non genererà un'eccezione.

dt2.GetValueOrDefault().ToString(format);

7

Visto che in realtà vuoi fornire il formato, ti suggerisco di aggiungere l'interfaccia IFormattable al metodo di estensione Smalls in questo modo, in questo modo non avrai la cattiva concatenazione del formato 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   
}

6

Che dire di qualcosa di così semplice:

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

5

Puoi usare dt2.Value.ToString("format"), ma ovviamente ciò richiede che dt2! = Null, e che neghi in primo luogo l'uso di un tipo nullable.

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


5

Ecco un approccio più generico. Ciò consentirà di formattare in stringa qualsiasi tipo di valore annullabile. Ho incluso il secondo metodo per consentire la sostituzione del valore di stringa predefinito invece di 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;
    }
}

4

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: 

4

Anche una soluzione migliore in C # 6.0:

DateTime? birthdate;

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

4

Sintassi RAZOR:

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

2

Penso che devi usare GetValueOrDefault-Methode. Il comportamento con ToString ("yy ...") non è definito se l'istanza è nulla.

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

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

2

Ecco la risposta eccellente di Blake come metodo di estensione. Aggiungi questo al tuo progetto e le chiamate nella domanda funzioneranno come previsto.
Significa che viene usato come MyNullableDateTime.ToString("dd/MM/yyyy"), con lo stesso output di MyDateTime.ToString("dd/MM/yyyy"), tranne per il fatto che il valore sarà "N/A"se DateTime è null.

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

1

IFormattable include anche un provider di formati che può essere utilizzato, poiché entrambi i formati di IFormatProvider possono essere nulli in dotnet 4.0

/// <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 ai parametri nominati puoi fare:

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

Nelle versioni precedenti di dotnet si verificano molti 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);
    }
}

1

Mi piace questa opzione:

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

0

Estensioni generiche semplici

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

-2

Forse è una risposta tardiva ma può aiutare chiunque altro.

Semplice è:

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

o usa semplicemente qualsiasi formato anziché "d".

Migliore


1
Questo errore quando nullabledatevariable.Value è null.
Giovanni C

-2

puoi usare la linea semplice:

dt2.ToString("d MMM yyyy") ?? ""
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.