Hoe kan ik een nullable DateTime formatteren met ToString()?

Hoe kan ik de nullable DateTime dt2converteren naar een opgemaakte 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:

geen overbelasting van methode die ToString nodig heeft
één argument


Antwoord 1, autoriteit 100%

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

EDIT: zoals vermeld in andere opmerkingen, controleer of er een niet-null-waarde is.

Bijwerken: zoals aanbevolen in de opmerkingen, extensiemethode:

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

En vanaf C# 6 kun je de null-voorwaardelijke operatorom de code nog meer te vereenvoudigen. De onderstaande uitdrukking retourneert null als de DateTime?null is.

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

Antwoord 2, autoriteit 22%

Probeer dit voor de maat:

Het werkelijke dateTime-object dat u wilt opmaken, bevindt zich in de eigenschap dt.Value en niet in het dt2-object zelf.

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

Antwoord 3, autoriteit 10%

Jullie zijn te veel bezig met het ontwikkelen van dit alles en maken het veel ingewikkelder dan het in werkelijkheid is. Belangrijk, stop met het gebruik van ToString en begin met het gebruik van tekenreeksopmaak zoals string.Format of methoden die tekenreeksopmaak ondersteunen, zoals Console.WriteLine. Hier is de voorkeursoplossing voor deze vraag. Dit is ook het veiligst.

Bijwerken:

Ik werk de voorbeelden bij met up-to-date methoden van de huidige C#-compiler. voorwaardelijke operators& tekenreeksinterpolatie

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

Uitvoer: (ik zet er enkele aanhalingstekens in zodat je kunt zien dat het terugkomt als een lege tekenreeks als het null is)

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

Antwoord 4, autoriteit 9%

C# 6.0 baby:

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


Antwoord 5, autoriteit 8%

Zoals anderen al hebben gezegd, moet je controleren op null voordat je ToString aanroept, maar om te voorkomen dat je jezelf herhaalt, kun je een extensiemethode maken die dat doet, zoiets als:

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

Die kan worden aangeroepen als:

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'

Antwoord 6, autoriteit 4%

Het probleem met het formuleren van een antwoord op deze vraag is dat je de gewenste output niet specificeert wanneer de nullable datetime geen waarde heeft. De volgende code zal in dat geval DateTime.MinValueuitvoeren en zal, in tegenstelling tot het momenteel geaccepteerde antwoord, geen uitzondering genereren.

dt2.GetValueOrDefault().ToString(format);

Antwoord 7, autoriteit 2%

Aangezien je echt het formaat wilt bieden, raad ik aan om de IFormattable-interface toe te voegen aan de Smalls-extensiemethode, op die manier heb je niet de vervelende aaneenschakeling van tekenreeksen.

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   
}

Antwoord 8, autoriteit 2%

Je kunt dt2.Value.ToString("format")gebruiken, maar dat vereist natuurlijk dat dt2 != null, en dat ontkent het gebruik van een nullable type in de eerste plaats.

Er zijn hier verschillende oplossingen, maar de grote vraag is: hoe wil je een null-datum opmaken?


Antwoord 9, autoriteit 2%

Hoe zit het met zoiets eenvoudigs als dit:

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

Antwoord 10, autoriteit 2%

RAZOR-syntaxis:

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

Antwoord 11

Hier is een meer algemene benadering. Hiermee kunt u elk type nullable-waarde opmaken. Ik heb de tweede methode toegevoegd om het overschrijven van de standaard tekenreekswaarde mogelijk te maken in plaats van de standaardwaarde voor het waardetype te gebruiken.

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

Antwoord 12

Kortste antwoord

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

Testen

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: 

Antwoord 13

Zelfs een betere oplossing in C# 6.0:

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

Antwoord 14

Ik vind deze optie leuk:

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

Other episodes