Comment puis-je formater un DateTime nullable avec ToString ()?

226

Comment puis-je convertir le nullTable DateTime dt2 en une chaîne formatée?

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:

aucune surcharge à la méthode ToString ne prend un argument

Edward Tanguay
la source
3
Bonjour, cela vous dérangerait-il de revoir les réponses acceptées et actuelles? Une réponse plus pertinente aujourd'hui pourrait être plus correcte.
iuliu.net

Réponses:

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

EDIT: Comme indiqué dans d'autres commentaires, vérifiez qu'il existe une valeur non nulle.

Mise à jour: comme recommandé dans les commentaires, méthode d'extension:

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

Et à partir de C # 6, vous pouvez utiliser l' opérateur de condition nulle pour simplifier encore plus le code. L'expression ci-dessous renverra null si le DateTime?est null.

dt2?.ToString("yyyy-MM-dd hh:mm:ss")
Blake Pettersson
la source
26
On dirait que ça me demande une méthode d'extension.
David Glenn
42
.La valeur est la clé
stuartdotnet
@David pas que la tâche n'est pas anodine ... stackoverflow.com/a/44683673/5043056
Sinjai
3
Êtes-vous prêt pour cela ... dt? .ToString ("jj / MMM / aaaa") ?? "" Grands avantages de C # 6
Tom McDonough
Erreur CS0029: impossible de convertir implicitement le type 'chaîne' en 'System.DateTime?' (CS0029). .Net Core 2.0
Oracular Man
80

Essayez ceci pour la taille:

L'objet dateTime réel que vous cherchez à formater se trouve dans la propriété dt.Value et non sur l'objet dt2 lui-même.

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

Vous êtes trop en train de concevoir tout cela et de le rendre beaucoup plus compliqué qu'il ne l'est vraiment. Chose importante, arrêtez d'utiliser ToString et commencez à utiliser le formatage de chaîne comme string.Format ou des méthodes qui prennent en charge le formatage de chaîne comme Console.WriteLine. Voici la solution préférée à cette question. C'est aussi le plus sûr.

Mettre à jour:

Je mets à jour les exemples avec les méthodes à jour du compilateur C # d'aujourd'hui. opérateurs conditionnels et interpolation de chaînes

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

Sortie: (je mets des guillemets simples pour que vous puissiez voir qu'elle revient comme une chaîne vide lorsqu'elle est nulle)

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

'2019-04-09 08:01:39'
''
John C
la source
30

Comme d'autres l'ont indiqué, vous devez vérifier la valeur null avant d'appeler ToString, mais pour éviter de vous répéter, vous pouvez créer une méthode d'extension qui fait cela, quelque chose comme:

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

}

Qui peut être invoqué comme:

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
la source
28

Bébé C # 6.0:

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

iuliu.net
la source
2
Je suggérerais la version suivante afin que cette réponse soit équivalente à la réponse acceptée existante pour C # 6.0. Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
Can Bud
15

Le problème avec la formulation d'une réponse à cette question est que vous ne spécifiez pas la sortie souhaitée lorsque le datetime nullable n'a aucune valeur. Le code suivant sortira DateTime.MinValuedans un tel cas, et contrairement à la réponse actuellement acceptée, ne lèvera pas d'exception.

dt2.GetValueOrDefault().ToString(format);
Matt Howells
la source
7

Voyant que vous voulez réellement fournir le format, je suggère d'ajouter l'interface IFormattable à la méthode d'extension Smalls comme ça, de cette façon, vous n'avez pas la concaténation de format de chaîne désagréable.

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
la source
6

Qu'en est-il de quelque chose d'aussi simple que cela:

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

Vous pouvez utiliser dt2.Value.ToString("format") , mais bien sûr cela nécessite que dt2! = Null, et cela annule l'utilisation d'un type nullable en premier lieu.

Il existe plusieurs solutions ici, mais la grande question est: comment voulez-vous formater une nulldate?

Henk Holterman
la source
5

Voici une approche plus générique. Cela vous permettra de formater une chaîne de n'importe quel type de valeur nullable. J'ai inclus la deuxième méthode pour permettre de remplacer la valeur de chaîne par défaut au lieu d'utiliser la valeur par défaut pour le type de valeur.

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
la source
4

Réponse la plus courte

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

Les 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
la source
4

Encore une meilleure solution en C # 6.0:

DateTime? birthdate;

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

Syntaxe RAZOR:

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

Je pense que vous devez utiliser la méthode GetValueOrDefault. Le comportement avec ToString ("yy ...") n'est pas défini si l'instance est nulle.

dt2.GetValueOrDefault().ToString("yyy...");
Martin
la source
1
Le comportement avec ToString ("yy ...") est défini si l'instance est nulle, car GetValueOrDefault () renverra DateTime.MinValue
Lucas
2

Voici l'excellente réponse de Blake comme méthode d'extension. Ajoutez ceci à votre projet et les appels dans la question fonctionneront comme prévu.
Cela signifie qu'il est utilisé comme MyNullableDateTime.ToString("dd/MM/yyyy"), avec la même sortie que MyDateTime.ToString("dd/MM/yyyy"), sauf que la valeur sera "N/A"si le DateTime est nul.

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

IFormattable comprend également un fournisseur de format qui peut être utilisé, il permet aux deux formats de IFormatProvider d'être nuls dans dotnet 4.0, ce serait

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

en utilisant avec des paramètres nommés, vous pouvez faire:

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

Dans les anciennes versions de dotnet, vous obtenez beaucoup de surcharges

/// <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
la source
1

J'aime cette option:

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

Extensions génériques simples

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
la source
-2

C'est peut-être une réponse tardive mais peut aider quelqu'un d'autre.

C'est simple:

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

ou utilisez simplement n'importe quel format plutôt que "d".

Meilleur

Waleed
la source
1
Cela entraînera une erreur lorsque nullabledatevariable.Value est null.
John C
-2

vous pouvez utiliser une ligne simple:

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