Verificando se uma variável DateTime teve um valor atribuído

131

Existe uma maneira fácil no C # para verificar se uma instância DateTime foi atribuída a um valor ou não?

Moo
fonte

Respostas:

82

A única maneira de ter uma variável que não foi atribuída a um valor em C # é que ela seja uma variável local - nesse caso, no tempo de compilação, você pode dizer que ela não é definitivamente atribuída tentando ler a partir dela: )

Eu suspeito que você realmente deseja Nullable<DateTime>(ou DateTime?com o açúcar sintático em C #) - faça com que nullcomece e atribua um DateTimevalor normal (que será convertido adequadamente). Em seguida, você pode simplesmente comparar com null(ou usar a HasValuepropriedade) para ver se um valor "real" foi definido.

Jon Skeet
fonte
Que tal verificar se o valor é igual ao valor padrão de data e hora. Existe alguma desvantagem imperceptível nessa abordagem? if (request.StartDateTime == default (DateTime) {request.StartDateTime = DateTime.Now;}
Menol
8
@ Menol: Bem, isso não indica a diferença entre um campo que recebeu deliberadamente um valor default(DateTime)e um que era exatamente assim. Basicamente, trata um valor dentro do domínio como "especial e indisponível para uso normal", o que não gosto.
Jon Skeet
298

você quer dizer assim:

DateTime datetime = new DateTime();

if (datetime == DateTime.MinValue)
{
    //unassigned
}

ou você pode usar Nullable

DateTime? datetime = null;

 if (!datetime.HasValue)
 {
     //unassigned
 }
Tem
fonte
5
Apenas o segundo deles é à prova de balas. O primeiro pressupõe algo sobre a representação não configurada de um DateTime que não é garantido pela estrutura. Pessoalmente, acho que eles deveriam ter adicionado um membro estático Unset para esse cenário.
Rupert Rawnsley 10/10
18
Para adicionar o que o @RupertRawnsley disse, você deve comparar com o padrão (DateTime), que é o valor de um DateTime não atribuído. Por acaso, é igual a MinValue, mas pode mudar.
Tsahi Asher
32

coloque isso em algum lugar:

public static class DateTimeUtil //or whatever name
{
    public static bool IsEmpty(this DateTime dateTime)
    {
        return dateTime == default(DateTime);
    }
}

então:

DateTime datetime = ...;

if (datetime.IsEmpty())
{
    //unassigned
}
sonatique
fonte
Eu gosto dessa ideia, mas observe que, no caso pouco provável de a variável DateTime ter sido atribuída a um valor que por acaso seja o valor padrão, esse método de extensão retornará o resultado errado. A única maneira de evitar isso é usar um DateTime anulável, que já foi sugerido. Eu ainda gosto muito (e agora estou usando) sua resposta, obrigado!
21919 Klicker
@ Klicker: Obrigado pelo seu bom comentário, mas não tenho certeza se entendi sua observação. Até onde eu sei, == nesse caso, sempre retornará true quando datetime for equivalente ao padrão (DateTime), seja qual for a maneira como o datetime final recebe o valor padrão. Deixe-me explicar: na verdade, o segundo trecho da minha resposta está errado, ele não será compilado, porque, se você considerar que esse é o corpo de uma função, o datetime não será atribuído e o compilador se recusará a usá-lo. Então você terá que atribuir um valor a ele. Pode ser o padrão (DateTime) direta ou indiretamente. Vou modificar minha resposta.
sonatique 03/02/19
e se, em outro contexto, datetime for membro de uma classe e permanecer como está, o tempo de execução atribuirá o padrão (DateTime) a ele. O == para estruturas realmente compara o conteúdo da estrutura, seja qual for a maneira como a estrutura é preenchida com esse conteúdo.
sonatique 03/02/19
Meu argumento realmente se refere apenas aos alunos, e o que quero dizer é; se você tiver um campo DateTime nível de classe ou propriedade que você atribuiu MinValue a, o seu IsEmptymétodo irá retornar true, o que provavelmente não é o que você quer (porque é não vazio - ele foi atribuído o valor padrão). Eu acho que o nome do seu método seria mais adequado como IsDefaultValue. Desde que você realmente não pode ter um DateTime não nulo IsEmpty.
Klicker 3/02/19
@ Klicker: ah sim, OK, entendi. Você está certo: o nome que escolhi é enganador. IsDefaultValueteria sido melhor
sonatique 5/05/19
5

DateTime é o tipo de valor, portanto, nunca pode ser nulo. Se você acha o DateTime? (Anulável), você pode usar:

DateTime? something = GetDateTime();
bool isNull = (something == null);
bool isNull2 = !something.HasValue;
TcKs
fonte
5

Acabei de descobrir que GetHashCode () para um datetime não atribuído é sempre zero. Não tenho certeza se essa é uma boa maneira de verificar se há data e hora nulas, porque não consigo encontrar nenhuma documentação sobre por que esse comportamento é exibido.

if(dt.GetHashCode()==0)
{
    Console.WriteLine("DateTime is unassigned"); 
} 
Arcturus
fonte
1
GetHashCode0 retorno porque de carrapatos (representação interna de datetime) são também igual a 0. código hash calculado através da seguinte maneira: unchecked((int)ticks) ^ (int)(ticks >> 32);. Também veja aqui: referencesource.microsoft.com/#mscorlib/system/datetime.cs,836
Ivan Kochurkin
Muito obrigado. Estou tentando serializar um arquivo XML de uma classe c # e excluir os atributos nulos. Isso ajudou.
Jim Neff
5

Use Nullable<DateTime>se possível.

baretta
fonte
3

Eu diria que o valor padrão é sempre new DateTime(). Para que possamos escrever

DateTime datetime;

if (datetime == new DateTime())
{
    //unassigned
}
Sabine
fonte
2
Esta solução já foi dada por + Hath em 2008 e, como + Rupert Rawnsley adicionado como comentário, não é à prova de balas ...
Roland Bär
0

Geralmente, prefiro, sempre que possível, usar o valor padrão dos tipos de valor para determinar se eles foram definidos. Obviamente, isso não é possível o tempo todo, especialmente com ints - mas para DateTimes, acho que reservar o MinValue para significar que não foi alterado é justo o suficiente. O benefício disso em relação às nuláveis ​​é que há um local a menos em que você obterá uma exceção de referência nula (e provavelmente em muitos lugares em que não é necessário procurar nulo antes de acessá-lo!)

Steve Dunn
fonte
0

Se você não precisa se preocupar com problemas de valor nulo, como verificar nulo toda vez que usá-lo ou agrupá-lo em alguma lógica, e também não deseja se preocupar com problemas de tempo de compensação, então isso é como eu resolvi o problema:

startDate = startDate < DateTime.MinValue.AddDays(1) ? keepIt : resetIt

Acabei de verificar se o valor padrão é inferior a um dia após o início dos tempos. Funciona como um encanto.

Urasquirrel
fonte