Verificando si una variable DateTime ha tenido un valor asignado

131

¿Hay alguna manera fácil dentro de C # para verificar si una instancia de DateTime ha recibido un valor o no?

Mugir
fuente

Respuestas:

83

La única forma de tener una variable a la que no se le ha asignado un valor en C # es que sea una variable local, en cuyo caso, en tiempo de compilación, puede decir que definitivamente no está asignada al intentar leer de ella: )

Sospecho que realmente quieres Nullable<DateTime>(o DateTime?con el azúcar sintáctico C #): haz que nullcomience y luego asigna un DateTimevalor normal (que se convertirá adecuadamente). Luego, puede comparar con null(o usar la HasValuepropiedad) para ver si se ha establecido un valor "real".

Jon Skeet
fuente
¿qué hay de verificar si el valor es igual al valor predeterminado de fecha y hora? ¿Hay algún inconveniente imperceptible en este enfoque? if (request.StartDateTime == default (DateTime) {request.StartDateTime = DateTime.Now;}
Menol
8
@Menol: Bueno, eso no dice la diferencia entre un campo al que se le ha dado un valor deliberadamente default(DateTime)y uno que era solo esa forma de comenzar. Básicamente se trata de un valor dentro del dominio como "especial y no disponible para uso normal" que no me gusta.
Jon Skeet
298

quieres decir así:

DateTime datetime = new DateTime();

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

o podrías usar Nullable

DateTime? datetime = null;

 if (!datetime.HasValue)
 {
     //unassigned
 }
Hath
fuente
55
Solo el segundo de estos es a prueba de balas. El primero supone algo sobre la representación no establecida de un DateTime que no está garantizado por el marco. Personalmente, creo que deberían haber agregado un miembro estático Unset para este escenario.
Rupert Rawnsley
18
Para agregar lo que dijo @RupertRawnsley, en realidad debería comparar con el valor predeterminado (DateTime), que es el valor de un DateTime no asignado. Resulta que es igual a MinValue, pero podría cambiar.
Tsahi Asher
32

pon esto en alguna parte:

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

luego:

DateTime datetime = ...;

if (datetime.IsEmpty())
{
    //unassigned
}
sonatique
fuente
Me gusta esta idea, pero tenga en cuenta que en el caso poco probable de que a la variable DateTime se le haya asignado un valor que resulta ser el valor predeterminado, este método de extensión devolverá el resultado incorrecto. La única forma de evitar esto es usar un DateTime anulable, que ya se ha sugerido. Sin embargo, todavía me gusta (y ahora estoy usando) tu respuesta, ¡gracias!
Klicker
@Klicker: Gracias por tu agradable comentario, pero no estoy seguro de entender tu comentario. Por lo que puedo decir, == en este caso siempre devolverá verdadero cuando datetime es equivalente a default (DateTime) cualquiera que sea la forma en que datetime termine asignando el valor predeterminado. Permítanme explicar: en realidad, el segundo fragmento de mi respuesta es incorrecto, no se compilará porque, si considera que este es el cuerpo de una función, entonces datetime no está asignado y el compilador se negará a usarlo. Entonces tendrá que asignarle un valor. Puede ser predeterminado (DateTime) directa o indirectamente. Modificaré mi respuesta
sonatique
y si en otro contexto datetime es miembro de una clase y se deja como está, el tiempo de ejecución le asignará el valor predeterminado (DateTime). El == para estructuras en realidad compara el contenido de la estructura, sea cual sea la forma en que la estructura termina llena con este contenido.
sonatique
Mi punto solo se relaciona realmente con los miembros de la clase, y lo que quiero decir es; si tiene un campo DateTime nivel de clase o propiedad que se ha asignado a MinValue, el IsEmptymétodo devolverá true, lo que probablemente no es lo que se quiere (porque es no vacío - que ha sido asignado el valor por defecto). Supongo que el nombre de su método sería más adecuado como IsDefaultValue. Dado que realmente no puede tener un DateTime no anulable eso IsEmpty.
Klicker
@Klicker: ah sí, está bien, lo tengo. Tienes razón: el nombre que elegí es engañoso. IsDefaultValuehubiera sido mejor
sonatique
5

DateTime es un tipo de valor, por lo que nunca puede ser nulo. Si piensas DateTime? (Anulable) puede usar:

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

Me acabo de enterar de que GetHashCode () para una fecha y hora no asignada siempre es cero. No estoy seguro de si esta es una buena manera de verificar la fecha y hora nulas, porque no puedo encontrar ninguna documentación sobre por qué se muestra este comportamiento.

if(dt.GetHashCode()==0)
{
    Console.WriteLine("DateTime is unassigned"); 
} 
Arcturus
fuente
1
GetHashCodedevuelve 0 a causa de garrapatas (representación interna de DateTime) son también igual a 0. código Hash calculado por la manera siguiente: unchecked((int)ticks) ^ (int)(ticks >> 32);. Ver también aquí: referencesource.microsoft.com/#mscorlib/system/datetime.cs,836
Ivan Kochurkin
Muchas gracias. Estoy tratando de serializar un archivo XML de una clase C # y excluir los atributos nulos. Esto ayudó
Jim Neff
5

Úselo Nullable<DateTime>si es posible.

baretta
fuente
3

Yo diría que el valor predeterminado es siempre new DateTime(). Para que podamos escribir

DateTime datetime;

if (datetime == new DateTime())
{
    //unassigned
}
Sabino
fuente
2
Esta solución ya fue dada por + Hath en 2008 y, como + Rupert Rawnsley agregó como comentario, no es a prueba de balas ...
Roland Bär
0

Generalmente prefiero, cuando sea posible, usar el valor predeterminado de los tipos de valor para determinar si se han establecido. Obviamente, esto no es posible todo el tiempo, especialmente con ints, pero para DateTimes, creo que reservar el MinValue para indicar que no se ha cambiado es lo suficientemente justo. El beneficio de esto sobre los valores nulables es que hay un lugar menos donde obtendrás una excepción de referencia nula (¡y probablemente muchos lugares donde no tienes que verificar si es nulo antes de acceder a él!)

Steve Dunn
fuente
0

Si no desea tener que preocuparse por los problemas de valor nulo, como verificar si es nulo cada vez que lo usa o resumirlo en alguna lógica, y tampoco desea preocuparse por los problemas de tiempo de compensación, entonces esto es Cómo resolví el problema:

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

Solo verifico que el valor predeterminado es menos de un día después del comienzo del tiempo. Funciona de maravilla.

Urasquirrel
fuente