Valor “nulo” de data e hora

Eu tenho procurado muito, mas não consegui encontrar uma solução. Como você lida com um DateTime que deve ser capaz de conter um valor não inicializado (equivalente a null)? Eu tenho uma class que pode ter um valor de propriedade DateTime definido ou não. Eu estava pensando em inicializar o detentor da propriedade para DateTime.MinValue, que então poderia ser facilmente verificado. Eu acho que esta é uma pergunta bastante comum, como você faz isso?

Para DateTimes normais, se você não inicializá-los, eles corresponderão a DateTime.MinValue , porque é um tipo de valor em vez de um tipo de referência.

Você também pode usar um DateTime anulável, assim:

 DateTime? MyNullableDate; 

Ou o formulário mais longo:

 Nullable MyNullableDate; 

E, finalmente, há um caminho embutido para referenciar o padrão de qualquer tipo. Isso retorna null para os tipos de referência, mas para o nosso exemplo DateTime, ele retornará o mesmo que DateTime.MinValue :

 default(DateTime) 

Se você estiver usando o .NET 2.0 (ou posterior), poderá usar o tipo anulável:

 DateTime? dt = null; 

ou

 Nullable dt = null; 

depois depois:

 dt = new DateTime(); 

E você pode verificar o valor com:

 if (dt.HasValue) { // Do something with dt.Value } 

Ou você pode usá-lo como:

 DateTime dt2 = dt ?? DateTime.MinValue; 

Você pode ler mais aqui:
http://msdn.microsoft.com/pt-br/library/b3h38hb0.aspx

Data hora? MyDateTime {get; set;}

 MyDateTime = (drOrder["Field1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)drOrder["Field1"]); 

Eu consideraria usar um tipo anulável .

DateTime? myDate DateTime? myDate vez de DateTime myDate .

Dessa forma, trabalhando bem

 myClass.PublishDate = toPublish ? DateTime.Now : (DateTime?)null; 

Por favor, note que a propriedade PublishDate deve ser DateTime?

Você pode usar uma class anulável.

 DateTime? date = new DateTime?(); 

Você pode usar um DateTime anulável para isso.

 Nullable myDateTime; 

ou a mesma coisa escrita assim:

 DateTime? myDateTime; 

Eu sempre defino a hora como DateTime.MinValue . Dessa forma, eu não obtenho nenhuma NullErrorException e posso compará-la a uma data que sei que não está definida.

Vale a pena ressaltar que, enquanto uma variável DateTime não pode ser null , ela ainda pode ser comparada a null sem um erro do compilador:

 DateTime date; ... if(date == null) // <-- will never be 'true' ... 

Você pode definir o DateTime como Nullable. Por padrão, o DateTime não é anulável. Você pode torná-lo anulável de duas maneiras. Usando um ponto de interrogação após o tipo DateTime? myTime ou usando o estilo genérico Nullable. Eu adicionei alguns links no msdn.

Usando Nullable

Anulável

Basta ser avisado – Ao usar um Nullable, obviamente, ele não é mais um object de data e hora ‘puro’, portanto, você não pode acessar os membros do DateTime diretamente. Vou tentar explicar.

Usando Nullable <> você está basicamente envolvendo o DateTime em um container (obrigado generics), que é anulável – obviamente, o seu propósito. Este contêiner tem suas próprias propriedades que você pode chamar que fornecerão acesso ao objeto DateTime mencionado anteriormente; depois de usar a propriedade correta – nesse caso, Nullable.Value – você terá acesso aos membros, propriedades etc. padrão do DateTime.

Então – agora a questão vem à mente sobre a melhor maneira de acessar o object DateTime. Existem algumas maneiras, o número 1 é de longe o melhor e 2 é “cara porquê”.

  1. Usando a propriedade Nullable.Value,

    DateTime date = myNullableObject.Value.ToUniversalTime(); //Works

    DateTime date = myNullableObject.ToUniversalTime(); //Not a datetime object, fails

  2. Convertendo o object anulável em datetime usando Convert.ToDateTime (),

    DateTime date = Convert.ToDateTime(myNullableObject).ToUniversalTime(); //works but why...

Embora a resposta esteja bem documentada neste momento, acredito que o uso do Nullable provavelmente tenha sido publicado. Desculpe se você não concordar.

edit: Removeu uma terceira opção, pois era um pouco excessivamente específica e dependente do caso.

Embora todos já tenham lhe dado a resposta, mencionarei uma maneira que facilita a passagem de um datetime para uma function.

[ERRO: não é possível converter o system.datetime? para system.datetime]

 DateTime? dt = null; DateTime dte = Convert.ToDateTime(dt); 

Agora você pode passar dentro da function sem problemas.

Se você está, às vezes, esperando nulo você poderia usar algo assim:

 var orderResults = Repository.GetOrders(id, (DateTime?)model.DateFrom, (DateTime?)model.DateTo) 

Em seu repository, use datetime com capacidade de nulo.

 public Orders[] GetOrders(string id, DateTime? dateFrom, DateTime? dateTo){...} 

Eu tive o mesmo problema que eu tive que dar Null como um parâmetro para DateTime durante a realização de teste de unidade para Throws ArgumentNullException.Ele trabalhou no meu caso usando a seguinte opção:

 Assert.Throws(()=>sut.StartingDate = DateTime.Parse(null)); 

Dada a natureza de um tipo de dados de data / hora, ele não pode conter um valor null , isto é, ele precisa conter um valor, não pode ficar em branco ou não conter nada. Se você marcar uma variável de data / hora como nullable , somente poderá atribuir um valor nulo a ela. Então, o que você está procurando fazer é uma das duas coisas (pode haver mais, mas só consigo pensar em duas):

  • Atribua um valor de data / hora mínimo à sua variável se você não tiver um valor para ela. Você também pode atribuir um valor máximo de data / hora – da maneira que melhor lhe convier. Apenas certifique-se de que você é consistente em todo o site ao verificar seus valores de data / hora. Decida usar min ou max e ficar com ele.

  • Marque sua variável de data / hora como nullable . Dessa forma, você pode definir sua variável de data / hora como null se não tiver uma variável para ela.

Deixe-me demonstrar meu primeiro ponto usando um exemplo. O tipo de variável DateTime não pode ser definido como null, ele precisa de um valor, nesse caso, eu o configurarei para o valor mínimo do DateTime se não houver nenhum valor.

Meu cenário é que eu tenho uma class BlogPost . Ele tem muitos campos / propriedades diferentes, mas eu escolhi apenas usar dois para este exemplo. DatePublished é quando a postagem foi publicada no site e precisa conter um valor de data / hora. DateModified é quando uma postagem é modificada, portanto, ela não precisa conter um valor, mas pode conter um valor.

 public class BlogPost : Entity { public DateTime DateModified { get; set; } public DateTime DatePublished { get; set; } } 

Usando o ADO.NET para obter os dados do database (atribua DateTime.MinValue se não houver valor):

 BlogPost blogPost = new BlogPost(); blogPost.DateModified = sqlDataReader.IsDBNull(0) ? DateTime.MinValue : sqlDataReader.GetFieldValue(0); blogPost.DatePublished = sqlDataReader.GetFieldValue(1); 

Você pode realizar meu segundo ponto marcando o campo DateModified como nullable . Agora você pode configurá-lo para null se não houver valor para ele:

 public DateTime? DateModified { get; set; } 

Usando o ADO.NET para obter os dados do database, ele parecerá um pouco diferente do que foi feito anteriormente (atribuindo null vez de DateTime.MinValue ):

 BlogPost blogPost = new BlogPost(); blogPost.DateModified = sqlDataReader.IsDBNull(0) ? (DateTime?)null : sqlDataReader.GetFieldValue(0); blogPost.DatePublished = sqlDataReader.GetFieldValue(1); 

Espero que isso ajude a esclarecer qualquer confusão. Dado que a minha resposta é cerca de 8 anos mais tarde, você é provavelmente um programador C # especializado até agora 🙂