Como posso formatar um DateTime anulável com ToString ()?

226

Como posso converter o DateTime dt2 anulável em uma seqüência de caracteres formatada?

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:

nenhuma sobrecarga para o método ToString leva um argumento

Edward Tanguay
fonte
3
Olá, você se importaria de revisar as respostas aceitas e as atuais? Uma resposta atual mais relevante pode estar mais correta.
Iuliu.net

Respostas:

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

EDIT: Como declarado em outros comentários, verifique se existe um valor não nulo.

Atualização: conforme recomendado nos comentários, método de extensão:

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

E a partir do C # 6, você pode usar o operador nulo-condicional para simplificar ainda mais o código. A expressão abaixo retornará nulo se DateTime?for nulo.

dt2?.ToString("yyyy-MM-dd hh:mm:ss")
Blake Pettersson
fonte
26
Parece que está implorando por um método de extensão para mim.
10139 David Glenn
42
.Value é a chave
stuartdotnet
@ David não que a tarefa não é trivial ... stackoverflow.com/a/44683673/5043056
Sinjai
3
Você está pronto para isso ... dt? .ToString ("dd / MMM / aaaa") ?? "" Grandes vantagens do C # 6
Tom McDonough
Erro CS0029: Não é possível converter implicitamente o tipo 'string' para 'System.DateTime?' (CS0029). .Net Core 2.0
Oracular Man
80

Tente isso para obter o tamanho:

O objeto dateTime real que você deseja formatar está na propriedade dt.Value, e não no próprio objeto dt2.

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

Vocês estão planejando tudo isso e tornando tudo muito mais complicado do que realmente é. Importante, pare de usar o ToString e comece a usar a formatação de string como string.Format ou métodos que suportam a formatação de string como Console.WriteLine. Aqui está a solução preferida para esta pergunta. Este também é o mais seguro.

Atualizar:

Eu atualizo os exemplos com métodos atualizados do compilador C # de hoje. operadores condicionais e interpolação de strings

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

Saída: (coloquei aspas simples para que você veja que ele volta como uma string vazia quando nulo)

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

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

Como outros já declararam, é necessário verificar se há nulo antes de chamar o ToString, mas para evitar se repetir, você pode criar um método de extensão que faça isso, 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 pode ser invocado 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'
David Glenn
fonte
28

Bebê C # 6.0:

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

iuliu.net
fonte
2
Eu sugeriria a versão a seguir para que essa resposta seja equivalente à resposta aceita existente para o C # 6.0. Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
Can Bud
15

O problema com a formulação de uma resposta para esta pergunta é que você não especifica a saída desejada quando o data / hora anulável não tem valor. O código a seguir será exibido DateTime.MinValuenesse caso e, diferentemente da resposta atualmente aceita, não emitirá uma exceção.

dt2.GetValueOrDefault().ToString(format);
Matt Howells
fonte
7

Visto que você realmente deseja fornecer o formato, sugiro adicionar a interface IFormattable ao método de extensão Smalls dessa maneira, para que você não tenha a concatenação desagradável do formato de string.

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
fonte
6

Que tal algo tão fácil como isto:

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

Você pode usar dt2.Value.ToString("format"), mas é claro que isso exige que dt2! = Null, e que negue o uso de um tipo anulável em primeiro lugar.

Existem várias soluções aqui, mas a grande questão é: como você deseja formatar uma nulldata?

Henk Holterman
fonte
5

Aqui está uma abordagem mais genérica. Isso permitirá que você formate uma string com qualquer tipo de valor anulável. Eu incluí o segundo método para permitir substituir o valor padrão da string em vez de usar o valor padrão para o 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;
    }
}
Schmalls
fonte
4

Resposta mais curta

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

Testes

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
fonte
4

Mesmo uma solução melhor no C # 6.0:

DateTime? birthdate;

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

Sintaxe RAZOR:

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

Eu acho que você tem que usar o GetValueOrDefault-Methode. O comportamento com ToString ("yy ...") não é definido se a instância for nula.

dt2.GetValueOrDefault().ToString("yyy...");
Martin
fonte
1
O comportamento com ToString ("yy ...") é definido se a instância for nula, porque GetValueOrDefault () retornará DateTime.MinValue
Lucas
2

Aqui está a excelente resposta de Blake como método de extensão. Adicione isso ao seu projeto e as chamadas na pergunta funcionarão conforme o esperado.
Significando que é usado como MyNullableDateTime.ToString("dd/MM/yyyy"), com a mesma saída que MyDateTime.ToString("dd/MM/yyyy"), exceto que o valor será "N/A"se o DateTime for nulo.

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

O IFormattable também inclui um provedor de formatos que pode ser usado, pois permite que ambos os formatos do IFormatProvider sejam nulos no 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 junto com parâmetros nomeados, você pode:

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

Nas versões mais antigas do dotnet, você recebe muitas 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);
    }
}
JeroenH
fonte
1

Eu gosto desta opção:

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

Extensões 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;
    }
}
Andzej Maciusovic
fonte
-2

Talvez seja uma resposta tardia, mas possa ajudar qualquer outra pessoa.

Simples é:

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

ou apenas use qualquer formato em vez de "d".

Melhor

Waleed
fonte
1
Isso ocorrerá quando nullabledatevariable.Value for nulo.
John C
-2

você pode usar uma linha simples:

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