2008-10-21 27 views
216

He estado buscando mucho pero no he podido encontrar una solución. ¿Cómo se maneja un DateTime que debería poder contener un valor no inicializado (equivalente a null)? Tengo una clase que puede tener un valor de propiedad DateTime establecido o no. Estaba pensando en inicializar el titular de la propiedad en DateTime.MinValue, que luego podría verificarse fácilmente. Supongo que esta es una pregunta bastante común, ¿cómo lo haces?DateTime valor "nulo"

Respuesta

332

Para DateTimes normal, si no los inicializa en absoluto, entonces coincidirán con DateTime.MinValue, porque es un tipo de valor en lugar de un tipo de referencia.

También puede utilizar un DateTime anulable, así:

DateTime? MyNullableDate; 

O el más largo formulario:

Nullable<DateTime> MyNullableDate; 

Y, por último, está construido en forma de referenciar el valor por defecto de cualquier tipo . Esto devuelve null para los tipos de referencia, pero para nuestro ejemplo DateTime se devolverá el mismo que DateTime.MinValue:

default(DateTime) 
+7

Sería de gran ayuda si proporciona un ejemplo de cómo usarlo. ¿Cómo se asigna el DateTime en la base de datos, que podría ser DBNull, al DateTime que se puede agregar? –

+6

También es bueno tener en cuenta que cuando los INICIES y con nulo, se les asigna 'DateTime.MinValue' también – jlafay

+1

@ kirk.burleson que parece una pregunta separada. – CompuChip

10

me gustaría considerar el uso de un nullable types.

DateTime? myDate en lugar de DateTime myDate.

71

Si está utilizando .NET 2.0 (o posterior), puede utilizar el tipo anulable:

DateTime? dt = null; 

o

Nullable<DateTime> dt = null; 

luego:

dt = new DateTime(); 

Y usted puede verificar el valor con:

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

O puede usarlo como:

DateTime dt2 = dt ?? DateTime.MinValue; 

Puede leer más aquí:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

+1

Puede usar tipos con posibilidad de nulos incluso en versiones anteriores de .NET, sin necesidad de 3.0. – stephenbayer

+1

Typo, actualizado eso. –

+1

Viene en .NET 2.0 ¿verdad? Los ? la sintaxis se agregó a VB.NET en 3.5, pero ha estado en C# desde 2.0, creo. –

5

Puede utilizar una clase anulable.

DateTime? date = new DateTime?(); 
5

Puede usar un DateTime que se puede nulos para esto.

Nullable<DateTime> myDateTime; 

o lo mismo escribe así:

DateTime? myDateTime; 
5

siempre fijo el tiempo para DateTime.MinValue. De esta forma, no recibo NullErrorException y puedo compararlo con una fecha que sé que no está configurada.

+8

Eso significa que no puede ver la diferencia entre "Realmente necesito un DateTime aquí" y "Es opcional" - Nullable es una solución mucho mejor, IMO. –

+0

? Realmente no entiendo tu comentario Sí, sé que cuando DateTime está tan lejos de la realidad es como si fuera nulo ... –

+0

Solo estoy sugiriendo otra solución. En lugar de repetir lo que se ha sugerido ya 10 veces aquí. –

4

Puede establecer DateTime en Nullable. Por defecto, DateTime no puede contener nulos. Puedes hacerlo anulable de varias maneras. ¿Utiliza un signo de interrogación después del tipo DateTime? myTime o usando el estilo genérico Nullable. He agregado un par de enlaces en msdn.

Using Nullable

Nullable

20

DateTime? MyDateTime {get; set;}

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

Si es así, a veces, esperando nula podría utilizar algo como esto:

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

En su uso de fecha y hora repositorio nulables.

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

Vale la pena señalar que, mientras que una variable DateTime no puede ser null, todavía se puede comparar con null sin un error de compilación:

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

Sólo se advirtió - Cuando se utiliza un anulable su obviamente ya no es un objeto de fecha y hora 'puro', como tal no se puede acceder directamente a los miembros de DateTime. Lo intentaré y lo explicaré.

Al usar Nullable <> básicamente está envolviendo DateTime en un contenedor (gracias a los genéricos) del cual es anulable, obviamente su propósito. Este contenedor tiene sus propias propiedades que puede llamar que proporcionarán acceso al objeto DateTime antes mencionado; después de usar la propiedad correcta - en este caso Nullable.Value - entonces tiene acceso a los miembros estándar DateTime, propiedades, etc.

Entonces, ahora el problema viene a la mente sobre la mejor manera de acceder al objeto DateTime. Hay algunas maneras, el número 1 es por lejos el mejor y 2 es "amigo por qué".

  1. Utilizando la propiedad Nullable.Value,

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

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

  2. la conversión del objeto anulable a fecha y hora usando Convert.ToDateTime(),

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

Aunque la respuesta está bien documentada en este punto, creo que vale la pena publicar sobre el uso de Nullable. Lo siento si no estás de acuerdo.

editar: Se eliminó una tercera opción, ya que era un poco demasiado específica y dependiente de cada caso.

2

Aunque todo el mundo ya le ha dado la respuesta, voy a mencionar una manera que hace que sea fácil de pasar una fecha y hora en una función

[ERROR: No se puede convertir System.DateTime? a System.DateTime]

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

Ahora usted puede pasar DTE dentro de la función sin ningún problema.

-1

Dada la naturaleza de un tipo de datos de fecha/hora, no puede contener un valor de null, es decir, debe contener un valor, no puede estar en blanco ni contener nada. Si marca una variable de fecha/hora como nullable, solo podrá asignarle un valor nulo. Así que lo que busca es hacer una de dos cosas (que podría haber más, pero sólo puedo pensar en dos):

  • Asignar un valor mínimo de fecha/hora a la variable si no tiene una valor para ello. También puede asignar un valor máximo de fecha/hora, según sea el que le sea conveniente. Solo asegúrese de ser coherente en todo el sitio cuando verifique los valores de fecha/hora. Decida usar min o max y quédese con él.

  • Marque la fecha/hora como nullable. De esta forma puede configurar su variable de fecha/hora en null si no tiene una variable.

Déjenme demostrar mi primer punto con un ejemplo. El tipo de variable DateTime no se puede establecer en nulo, necesita un valor, en este caso voy a establecerlo en el valor mínimo DateTime si no hay ningún valor.

Mi caso es que tengo una clase BlogPost. Tiene muchos campos/propiedades diferentes, pero elegí solo usar dos para este ejemplo. DatePublished es cuando la publicación se publicó en el sitio web y debe contener un valor de fecha/hora. DateModified es cuando se modifica una publicación, por lo que no tiene que contener un valor, pero puede contener un valor.

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

    public DateTime DatePublished { get; set; } 
} 

Usando ADO.NET para obtener los datos de la base de datos (es decir asignar DateTime.MinValue no hay ningún valor):

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

Usted puede lograr mi segundo punto, marcando el campo DateModified como nullable. Ahora se puede configurar para null si no hay ningún valor para él:

public DateTime? DateModified { get; set; } 

Usando ADO.NET para obtener los datos de la base de datos, que se verá un poco diferente a la forma en que se hizo anteriormente (asignación null en lugar de DateTime.MinValue):

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

Espero que esto ayude a aclarar cualquier confusión. Teniendo en cuenta que mi respuesta es de unos 8 años más tarde que son, probablemente, un experto programador de C# por ahora :)

7

De esa forma de trabajo, así

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

Tenga en cuenta que PublishDate propiedad debe ser DateTime?

1

tuve el mismo problema que tuviera que dar Null como parámetro para DateTime mientras se realiza la prueba Unidad de Lanza ArgumentNullException.It trabajó en mi caso usando la siguiente opción:

Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null)); 
Cuestiones relacionadas