Jak sformatować zerową wartość DateTime za pomocą ToString ()?

226

Jak przekonwertować zerowalne DateTime dt2 na sformatowany ciąg?

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:

brak przeciążenia metody ToString wymaga jednego argumentu

Edward Tanguay
źródło
3
Witaj, czy mógłbyś przejrzeć zaakceptowane i aktualne odpowiedzi? Bardziej trafna odpowiedź dnia może być bardziej poprawna.
iuliu.net

Odpowiedzi:

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

EDYCJA: Jak stwierdzono w innych komentarzach, sprawdź, czy nie ma wartości zerowej.

Aktualizacja: zgodnie z zaleceniami w komentarzach, metoda rozszerzenia:

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

Począwszy od C # 6, możesz użyć operatora warunkowego null, aby jeszcze bardziej uprościć kod. Poniższe wyrażenie zwróci null, jeśli DateTime?null.

dt2?.ToString("yyyy-MM-dd hh:mm:ss")
Blake Pettersson
źródło
26
Wygląda na to, że błaga mnie o metodę rozszerzenia.
David Glenn
42
.Value jest kluczem
stuartdotnet
@Dawid nie, że to zadanie nie jest trywialne ... stackoverflow.com/a/44683673/5043056
Sinjai
3
Czy jesteś gotowy na to ... dt? .ToString („dd / MMM / rrrr”)? „” Wielkie zalety C # 6
Tom McDonough
Błąd CS0029: Nie można niejawnie przekonwertować typu „string” na „System.DateTime?” (CS0029). .Net Core 2.0
Oracular Man
80

Spróbuj tego dla rozmiaru:

Rzeczywisty obiekt dateTime, który chcesz sformatować, znajduje się we właściwości dt.Value, a nie w samym obiekcie dt2.

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

Wy wszyscy jesteście nad inżynierią i wszystko to sprawia, że ​​jest to o wiele bardziej skomplikowane niż w rzeczywistości. Ważna rzecz: przestań używać ToString i zacznij korzystać z formatowania ciągów, takich jak string.Format lub metod, które obsługują formatowanie ciągów, takich jak Console.WriteLine. Oto preferowane rozwiązanie tego pytania. Jest to również najbezpieczniejsze.

Aktualizacja:

Aktualizuję przykłady za pomocą aktualnych metod dzisiejszego kompilatora C #. operatory warunkowe i interpolacja ciągów

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

Dane wyjściowe: (umieszczam w nim pojedyncze cudzysłowy, abyś mógł zobaczyć, że wraca jako pusty ciąg znaków, gdy jest pusty)

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

'2019-04-09 08:01:39'
''
John C.
źródło
30

Jak stwierdzili inni, przed wywołaniem ToString należy sprawdzić wartość null, ale aby uniknąć powtarzania się, można utworzyć metodę rozszerzenia, która to robi, na przykład:

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

}

Które można wywołać jak:

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
źródło
28

Dziecko C # 6.0:

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

iuliu.net
źródło
2
Sugerowałbym następującą wersję, aby ta odpowiedź była równoważna z istniejącą odpowiedzią zaakceptowaną dla C # 6.0. Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
Can Bud,
15

Problem z sformułowaniem odpowiedzi na to pytanie polega na tym, że nie określa się żądanego wyniku, gdy zerowa data / godzina nie ma żadnej wartości. W DateTime.MinValuetakim przypadku wyświetli się następujący kod, w przeciwieństwie do obecnie akceptowanej odpowiedzi, nie zgłosi wyjątku.

dt2.GetValueOrDefault().ToString(format);
Matt Howells
źródło
7

Widząc, że naprawdę chcesz podać format, sugeruję dodanie interfejsu IFormattable do metody rozszerzenia Smalls w ten sposób, aby nie mieć nieprzyjemnego połączenia formatu łańcucha.

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
źródło
6

Co powiesz na coś tak prostego:

String.Format("{0:dd/MM/yyyy}", d2)
Max Brown
źródło
5

Możesz użyć dt2.Value.ToString("format"), ale oczywiście wymaga to, aby dt2! = Null, i to przede wszystkim neguje użycie typu zerowalnego.

Jest tu kilka rozwiązań, ale najważniejsze pytanie brzmi: jak sformatować nulldatę?

Henk Holterman
źródło
5

Oto bardziej ogólne podejście. Umożliwi to formatowanie dowolnego typu wartości dopuszczającej wartości zerowe. Podałem drugą metodę, aby umożliwić zastąpienie domyślnej wartości ciągu zamiast używania wartości domyślnej dla typu wartości.

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
źródło
4

Najkrótsza odpowiedź

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

Testy

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
źródło
4

Jeszcze lepsze rozwiązanie w C # 6.0:

DateTime? birthdate;

birthdate?.ToString("dd/MM/yyyy");
Mohammed Noureldin
źródło
4

Składnia RAZOR:

@(myNullableDateTime?.ToString("yyyy-MM-dd") ?? String.Empty)
wut
źródło
2

Myślę, że musisz użyć metody GetValueOrDefault-Methode. Zachowanie w przypadku ToString („yy ...”) nie jest zdefiniowane, jeśli instancja ma wartość NULL.

dt2.GetValueOrDefault().ToString("yyy...");
jaskółka oknówka
źródło
1
Zachowanie w ToString („yy ...”) jest zdefiniowane, jeśli instancja ma wartość NULL, ponieważ funkcja GetValueOrDefault () zwróci DateTime.MinValue
Lucas
2

Oto doskonała odpowiedź Blake'a jako metody rozszerzenia. Dodaj to do swojego projektu, a wywołania w pytaniu będą działać zgodnie z oczekiwaniami.
Oznacza to, że używa się go MyNullableDateTime.ToString("dd/MM/yyyy")z tym samym wyjściem co MyDateTime.ToString("dd/MM/yyyy"), z tym wyjątkiem, że wartość będzie miała wartość, "N/A"jeśli DateTime ma wartość null.

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

IFormattable zawiera również dostawcę formatu, którego można użyć, pozwala to, aby zarówno format IFormatProvider był zerowy w dotnet 4.0, byłoby to

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

używając razem z nazwanymi parametrami możesz:

dt2.ToString (defaultValue: „n / a”);

W starszych wersjach dotnet występuje wiele przeciążeń

/// <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
źródło
1

Podoba mi się ta opcja:

Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss") ?? "n/a");
Jaskółka oknówka
źródło
0

Proste rozszerzenia ogólne

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
źródło
-2

Może to późna odpowiedź, ale może pomóc każdemu innemu.

Proste jest:

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

lub po prostu użyj dowolnego formatu zamiast „d”.

Najlepsza

Waleed
źródło
1
Wystąpi błąd, gdy zmienna nullabledatevariable.Value ma wartość null.
John C,
-2

możesz użyć prostej linii:

dt2.ToString("d MMM yyyy") ?? ""
Daniel Heo
źródło