Valor de fecha y hora "nulo"

273

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

Colchonetas
fuente

Respuestas:

420

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

También puede usar un DateTime anulable, como este:

DateTime? MyNullableDate;

O la forma más larga:

Nullable<DateTime> MyNullableDate;

Y, finalmente, hay una forma integrada de hacer referencia al valor predeterminado de cualquier tipo. Esto devuelve nullpara los tipos de referencia, pero para nuestro ejemplo de DateTime devolverá lo mismo que DateTime.MinValue:

default(DateTime)

o, en versiones más recientes de C #,

default
Joel Coehoorn
fuente
8
Sería de gran ayuda si proporciona un ejemplo de cómo usarlo. ¿Cómo asigna el DateTime en la base de datos, que podría ser DBNull, al DateTime anulable?
kirk.burleson
9
También es bueno tener en cuenta que cuando ellos y con nula QUÉ inicializar, se les asigna DateTime.MinValue, así
Jeff LaFay
2
@ kirk.burleson que parece una pregunta separada.
CompuChip
tendrá MyNullableDate=date; que configurarlo, MyDate = MyNullableDate.Value;leerlo y if(MyNullableDate.HasValue)verificar si es nulo
satibel
Para aclarar un poco la respuesta "finalmente", el valor predeterminado de Nullable <DateTime> (DateTime?) Es nulo, porque Nullable <T> crea un tipo de referencia.
ryanwebjackson
88

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

DateTime? dt = null;

o

Nullable<DateTime> dt = null;

Entonces despúes:

dt = new DateTime();

Y puede verificar el valor con:

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

O puedes usarlo como:

DateTime dt2 = dt ?? DateTime.MinValue;

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

Mark Ingram
fuente
1
Puede usar tipos anulables incluso en versiones anteriores de .NET, sin necesidad de 3.0.
stephenbayer
1
Llegó en .NET 2.0 ¿verdad? Los ? La sintaxis se agregó a VB.NET en 3.5, pero creo que ha estado en C # desde 2.0.
David Mohundro
1
Los tipos anulables están disponibles en .Net 2.0. C # ha tenido la taquigrafía? notación de 2.0. ¿Solo VB.Net no tenía la taquigrafía? en 2.0 pero puede usar Nullable (Of DateTime)
Mendelt
Para el último fragmento, diría DateTime dt2 = dt ?? DateTime.MinValue;
Joel Coehoorn
Yo usaría dt.GetValueOrDefault(), es la opción más eficiente.
CompuChip
37

¿Fecha y hora? MyDateTime {get; set;}

MyDateTime = (dr["f1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)dr["f1"]);
Iman
fuente
1
Esto me ayudó a descubrir que pasar simplemente nullno funciona. Tiene que ser (DateTime?)null.
Fractales infinitas
33

Seguir el camino también funciona

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

Tenga en cuenta que la propiedad PublishDate debe ser DateTime?

Aleksei
fuente
12

Consideraría usar un tipo anulable .

DateTime? myDateen lugar de DateTime myDate.

David Mohundro
fuente
8

Vale la pena señalar que, si bien una DateTimevariable no puede ser null, todavía se puede comparar nullsin un error del compilador:

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

Puede usar una clase anulable.

DateTime? date = new DateTime?();
Aaron Smith
fuente
Probablemente valga la pena señalar que esto le dará un comportamiento diferente al de instanciar un no anulable DateTime. Como se mencionó anteriormente, new DateTime()efectivamente le dará, DateTime.Minmientras que new DateTime?()dará como resultado nulo.
Vitoc
6

Puede usar un DateTime anulable para esto.

Nullable<DateTime> myDateTime;

o lo mismo escrito así:

DateTime? myDateTime;
Patrik Svensson
fuente
6

Puede establecer DateTime en Nullable. Por defecto, DateTime no es anulable. Puede hacerlo anulable de varias maneras. ¿Usa un signo de interrogación después del tipo DateTime? myTime o usando el estilo genérico Nullable.

DateTime? nullDate = null;

o

DateTime? nullDate;
usuario29958
fuente
5

Siempre pongo el tiempo para DateTime.MinValue. De esta forma no obtengo ninguna NullErrorException y puedo compararla con una fecha que sé que no está establecida.

Patrick Desjardins
fuente
8
Eso significa que no puede distinguir la diferencia entre "Realmente necesito un DateTime aquí" y "Es opcional": Nullable <DateTime> es una solución mucho mejor, en mi opinión.
Jon Skeet
? Realmente no entiendo tu comentario. Sí, sé cuándo DateTime está tan lejos de la realidad como si fuera nulo ...
Patrick Desjardins
2
Es conveniente, pero veo DateTime.MinValue como un valor, no como una condición de caso especial. Solo puede conducir a problemas en el futuro. Yo iría con Nullable <DateTime>.
spoulson
3
Creo que extrañas algo de mi respuesta, Spoulson escribió algo y yo estaba respondiendo. Sobre los miembros públicos, bueno, no es lo mismo y tú lo sabes. es como String. Vacío o nulo. Puede hacer ambas cosas, no porque String.Empty sea mejor que null esté mal. Lo que sea.
Patrick Desjardins el
1
Estoy con Daok en esto. Puede que no sea el enfoque "por el libro", pero es mejor que obtener una NullReferenceException o tratar con el engorroso tipo Nullable. Además, ¿cuántas aplicaciones hay que realmente necesiten hacer referencia a la fecha 1 de enero del año 1 de nuestra era?
Jacobs Data Solutions el
4

Solo se advirtió: cuando se utiliza un Nullable, obviamente ya no es un objeto de fecha y hora "puro", como tal, no puede acceder directamente a los miembros de DateTime. Trataré de explicarlo.

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

Entonces, ahora me viene a la mente la mejor forma de acceder al objeto DateTime. Hay algunas maneras, el número 1 es, con diferencia, el mejor y el 2 es "amigo por qué".

  1. Usando la propiedad Nullable.Value,

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

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

  2. Convirtiendo el objeto anulable a datetime usando Convert.ToDateTime (),

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

Aunque la respuesta está bien documentada en este punto, creo que probablemente valga la pena publicar 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 dependía de mayúsculas y minúsculas.

Gabe
fuente
2

Aunque todos ya le han dado la respuesta, mencionaré una forma que facilita pasar una fecha y hora a una función

[ERROR: no se puede convertir system.datetime? a system.datetime]

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

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

No hay vacaciones
fuente
1

Si, a veces, espera nulo, podría usar algo como esto:

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

En su repositorio use datetime nulo.

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

Tuve el mismo problema que tuve que darle a Null como parámetro para DateTime mientras realizaba la prueba de unidad para Throws ArgumentNullException. Funcionó en mi caso usando la siguiente opción:

Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null));
Kiril Dobrev
fuente
0

Dada la naturaleza de un tipo de datos de fecha / hora, no puede contener un nullvalor, es decir, debe contener un valor, no puede estar en blanco o no contener nada. Si marca una variable de fecha / hora como nullablesolo entonces puede asignarle un valor nulo. Entonces, lo que está buscando hacer es una de dos cosas (puede haber más, pero solo puedo pensar en dos):

  • Asigne un valor mínimo de fecha / hora a su variable si no tiene un valor para ella. También puede asignar un valor máximo de fecha / hora, de la forma que más le convenga. Solo asegúrese de ser consistente en todo el sitio cuando verifique sus valores de fecha / hora. Decide usar mino maxy quédate con él.

  • Marque su variable de fecha / hora como nullable. De esta manera, puede establecer su variable de fecha / hora nullsi no tiene una variable.

Permítanme demostrar mi primer punto usando un ejemplo. El DateTimetipo de variable no se puede establecer en nulo, necesita un valor, en este caso voy a establecerlo en el DateTimevalor mínimo si no hay ningún valor.

Mi escenario es que tengo una BlogPostclase. Tiene muchos campos / propiedades diferentes, pero elegí solo usar dos para este ejemplo. DatePublishedes cuando la publicación se publicó en el sitio web y debe contener un valor de fecha / hora. DateModifiedes 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; }
}

Utilizando ADO.NETpara obtener los datos de la base de datos (asignar DateTime.MinValuees que no hay valor):

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

Puedes lograr mi segundo punto marcando el DateModifiedcampo como nullable. Ahora puede configurarlo nullsi no tiene ningún valor:

public DateTime? DateModified { get; set; }

Utilizando ADO.NETpara obtener los datos de la base de datos, se verá un poco diferente a la forma en que se hizo anteriormente (asignando en nulllugar 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. Dado que mi respuesta es aproximadamente 8 años después, probablemente ya seas un programador experto de C # :)

Brendan Vogt
fuente