¿Cómo puedo formatear un DateTime anulable con ToString ()?


226

¿Cómo puedo convertir el DateTime dt2 anulable en una cadena formateada?

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:

sin sobrecarga al método ToString toma un argumento


3
Hola, ¿te importaría revisar las respuestas aceptadas y actuales? Una respuesta actual más relevante podría ser más correcta.
iuliu.net

Respuestas:


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

EDITAR: como se indicó en otros comentarios, verifique que haya un valor no nulo.

Actualización: como se recomienda en los comentarios, método de extensión:

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

Y a partir de C # 6, puede usar el operador condicional nulo para simplificar aún más el código. La siguiente expresión devolverá nulo si DateTime?es nulo.

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

26
Parece que me está pidiendo un método de extensión.
David Glenn

42
El valor es la clave
stuartdotnet

@David no es que la tarea no sea trivial ... stackoverflow.com/a/44683673/5043056
Sinjai

3
¿Estás listo para esto ... dt? .ToString ("dd / MMM / aaaa") ?? "" Grandes ventajas de C # 6
Tom McDonough

Error CS0029: ¿No se puede convertir implícitamente el tipo 'cadena' a 'System.DateTime?' (CS0029). .Net Core 2.0
Oracular Man

80

Probar esto para el tamaño:

El objeto dateTime real que desea formatear está en la propiedad dt.Value, y no en el objeto dt2 en sí.

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

36

Ustedes están sobre ingeniería todo esto y lo hacen mucho más complicado de lo que realmente es. Lo importante, deje de usar ToString y comience a usar el formato de cadena como string.Format o los métodos que admiten el formato de cadena como Console.WriteLine. Aquí está la solución preferida para esta pregunta. Este es también el más seguro.

Actualizar:

Actualizo los ejemplos con métodos actualizados del compilador de C # de hoy. operadores condicionales e interpolación de cadenas

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

Salida: (pongo comillas simples para que pueda ver que vuelve como una cadena vacía cuando es nulo)

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

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

30

Como otros han dicho, debe verificar si hay valores nulos antes de invocar ToString, pero para evitar repetirse, puede crear un método de extensión que haga eso, algo como:

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

}

Que se puede invocar como:

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 bebé:

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


2
Sugeriría la siguiente versión para que esta respuesta sea equivalente a la respuesta aceptada existente para C # 6.0. Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
Puede Bud

15

El problema con la formulación de una respuesta a esta pregunta es que no especifica la salida deseada cuando la fecha y hora anulable no tiene valor. El siguiente código saldrá DateTime.MinValueen tal caso y, a diferencia de la respuesta actualmente aceptada, no arrojará una excepción.

dt2.GetValueOrDefault().ToString(format);

7

Al ver que realmente desea proporcionar el formato, le sugiero que agregue la interfaz IFormattable al método de extensión Smalls de esta manera, de esa manera no tiene la concatenación de formato de cadena desagradable.

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

¿Qué pasa con algo tan fácil como esto?

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

5

Puede usar dt2.Value.ToString("format"), pero, por supuesto, eso requiere que dt2! = Null, y eso niega el uso de un tipo anulable en primer lugar.

Aquí hay varias soluciones, pero la gran pregunta es: ¿cómo desea formatear una nullfecha?


5

Aquí hay un enfoque más genérico. Esto le permitirá formatear en cadena cualquier tipo de valor anulable. He incluido el segundo método para permitir reemplazar el valor de cadena predeterminado en lugar de usar el valor predeterminado para el tipo de valor.

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

Respuesta más corta

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

Pruebas

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

Sintaxis de RAZOR:

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

2

Creo que tienes que usar GetValueOrDefault-Methode. El comportamiento con ToString ("aa ...") no está definido si la instancia es nula.

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

1
El comportamiento con ToString ("aa ...") se define si la instancia es nula, porque GetValueOrDefault () devolverá DateTime.MinValue
Lucas

2

Aquí está la excelente respuesta de Blake como método de extensión. Agregue esto a su proyecto y las llamadas en la pregunta funcionarán como se esperaba.
Lo que significa que se usa como MyNullableDateTime.ToString("dd/MM/yyyy"), con el mismo resultado que MyDateTime.ToString("dd/MM/yyyy"), excepto que el valor será "N/A"si DateTime es nulo.

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

1

IFormattable también incluye un proveedor de formatos que se puede usar, permite que ambos formatos de IFormatProvider sean nulos en dotnet 4.0, esto sería

/// <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 junto con parámetros con nombre que puedes hacer:

dt2.ToString (Valor predeterminado: "n / a");

En versiones anteriores de dotnet obtienes muchas sobrecargas

/// <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

Me gusta esta opcion:

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

0

Extensiones genéricas 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;
    }
}

-2

Tal vez sea una respuesta tardía, pero puede ayudar a cualquier otra persona.

Simple es:

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

o simplemente use cualquier formato en lugar de "d".

Mejor


1
Esto generará un error cuando nullabledatevariable.Value sea nulo.
John C

-2

puedes usar una línea simple:

dt2.ToString("d MMM yyyy") ?? ""
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.