Cuidado con las horas de las fechas en las consultas de SQL

 

Pues eso… que esto de las fechas en las consultas es como el cuento de nunca acabar… al menos para mí, jeje.

Lo que me ha pasado esta vez es que he estado usando fechas en una consulta y, como ya comenté hace años, la mejor forma de pasarlas a la consulta de SQL es usando parámetros, hasta aquí todo bien.

 

' Crear un nuevo objeto del tipo DataAdapter
da = New SqlDataAdapter(sel, sCon)
da.SelectCommand.Parameters.AddWithValue("@fecha1", fecha1)
da.SelectCommand.Parameters.AddWithValue("@fecha2", fecha2)

 

En esta ocasión, las fechas las he pasado como argumento a un método normal con el tipo de datos de las fechas (DateTime o Date en VB). Aclaro esto porque cuando se convierte un objeto del tipo fecha a una cadena (que es lo que supongo que hace el SQL cuando va a trabajar con la fecha) ese objeto del tipo fecha se convierte en una fecha y una hora (ver la figura 1).

fechas_sql_02jun2016_peq
Figura 1. Los objetos de tipo Date (DateTime) contienen la fecha y la hora.

En este ejemplo, el valor pasado en el primer argumento tiene la fecha y la hora a las 12 de la madrugada, es decir a las 00:00:00 que es lo que ocurre cuando conviertes una fecha de cadena a tipo DateTime.

Pero si la fecha la obtienes, por ejemplo, de un DateTimePicker o simplemente usando DateTime.Now que obtiene la fecha (y hora) actual. En el caso de que ese valor se obtenga a la hora en que escribo esto, mostrará un valor de fecha 2 de junio de 2016 y la hora 13 (01 PM) y 24 minutos con nosecuantos segundos (ver la figura 2).

fechas_sql_02jun2016_2
Figura 2. Now devuelve la fecha y hora actual completa.

En este caso la propiedad Now del objeto fecha devuelve la fecha y la hora actual, y lo que hace la función esa que muestro en la figura 2 (NowDate) es devolver solo la fecha, sin hora… aunque la hora siempre está, pero si no se indica será 00:00:00 (media noche).

 

Bueno, espero que te pueda servir de ayuda en casos como el que me pasó a mí, que aún habiendo un dato (de la misma fecha en la que hacía la comprobación) no me lo mostraba porque la hora era (por ejemplo las 9 de la noche) y esa fecha no era igual (o menor) que la que estaba guardada en la base de datos (que era el mismo día, pero a las cero horas), en fin…

Nos vemos.
Guillermo

Esta entrada fue publicada en cosas técnicas, mis cosas y etiquetada , , , , . Guarda el enlace permanente.

7 respuestas a Cuidado con las horas de las fechas en las consultas de SQL

  1. Dani Seara dijo:

    Por eso, estimado amigo, VB tiene Today que solo retorna la fecha .).
    A más, Siempre los parámetros con tipo asi se sabe que son fechas. Y, si por cualquier cosa, fueran como cadena, con formato aaaa-mm-dd que se entiende siempre.
    Y, si decimos “las ventas de hoy”, el desde es Today, y el hasta es Today +1 (si eres quisquilloso, dateadd(“s”,-1,Today+1) 🙂 para que sea desde el principio del día de hoy, hasta el último segundo del día de hoy :).

    • elGuille dijo:

      jajaja… muy acertado amigo Dani (como siempre) pero hay que darle un poco de “chance” a los que no usan el VB… 😉

  2. Cuando dices “Aclaro esto porque cuando se convierte un objeto del tipo fecha a una cadena (que es lo que supongo que hace el SQL cuando va a trabajar con la fecha)” si se interpreta que internamente el SQL Server lo manipula como una cadena no es correcto. La fecha en SQL Server es precisamente eso, una fecha y se almacena como un conjunto de bytes dependiendo del tipo especifico.
    A modo de ejemplo el formato DATETIME se almacena internamente como dos enteros de 4 bytes que representan la diferencia de fecha en días desde el 01/01/1900 y la diferencia en TICS del reloj desde la ultima medianoche.

    Dejo un script para que lo comprueben.

    DECLARE
    @Ahora datetime,
    @UltimaMedianoche datetime
    SELECT @Ahora = getdate()
    select @UltimaMedianoche = cast(getdate() as date)
    SELECT @Ahora, @UltimaMedianoche

    — Representacion interna
    SELECT CONVERT (varbinary(8), @Ahora)

    — Numero de dias que pasaron desde 01/01/1900
    SELECT CONVERT (int, SUBSTRING (CONVERT (varbinary(8), @Ahora), 1, 4))
    — Comprobacion
    Select datediff(dd,’19000101′,@Ahora)

    — numero de clock ticks que pasaron desde la ultima medianoche (se produce uno cada 3.33 ms)
    SELECT CONVERT (int, SUBSTRING (CONVERT (varbinary(8), @Ahora), 5, 4))
    — Comprobacion
    Select cast (datediff( ms,@UltimaMedianoche,@Ahora) * 3.0 /10.0 AS INT)

  3. juan esteban dijo:

    amigos, yo tenia el mismo problema. La solución no utilizar tipos de datos DateTime o Date en VB. En su lugar cuando necesito almacenar fecha utilizo campos de tipo NUMERICO o VARCHAR pero las formateo (AAAAMMDD) de tal manera que cuando las necesite las pues utilizar sin mayor problema. Asi mismo en un DateTimePicker he creado las funciones necesarias para convertir ese valor en el formato que necesito almacenar, es decir si el DateTimePicker tiene el formato DD/MM/AAAA, antes de almacenar paso ese valor por la nueva función para que me almacene en formato AAAAMMDD en un campo de tipo VARCHAR o NUMERICO

  4. David dijo:

    Puedes usar el método .date de una variable tipo DateTime para obtener sólo la fecha.
    La hora de la deja en las 12 de la noche.

  5. David dijo:

    Puedes usar la propiedad .date de una variable tipo DateTime para obtener sólo la fecha.
    La hora de la deja en las 12 de la noche.

Los comentarios están cerrados.