Skip to content
Empieza gratis

¿Por qué BETWEEN pierde el último día? Filtrar fechas con hora

Filtra un día, un mes o una semana completos aunque la columna tenga hora, con un intervalo semiabierto que no pierde el último día.

Curso gratis. Tu Maestro, una IA, .

Los pedidos en línea

Café Altura también vende por internet. La tienda en línea guarda cada pedido en la tabla pedidos: un pedido_id, el momento en que se creó (creado_utc) y el total en pesos. Son 304 pedidos sintéticos de febrero y marzo de 2026.

Esta columna ya es una fecha, no un texto, pero trae algo más: la hora. El primer pedido se creó el 2026-02-01 02:44:40. A una fecha con hora se le llama timestamp, y en DuckDB su tipo es TIMESTAMP.

El nombre de la columna dice utc: esas horas están en UTC, no en la hora de Ciudad de México. Eso lo resuelves en la siguiente lección. Aquí el problema es otro, y aparece aunque todo estuviera en tu hora local. Predice.

Cuatro pedidos de fin de marzo, con hora, y dos maneras de quedarte con los de marzo. Escribe qué crees que imprime cada programa y por qué.

Cuatro pedidos de fin de marzo, con hora, y dos maneras de quedarte con los de marzo. Escribe qué crees que imprime cada programa y por qué.

Marzo con <= '2026-03-31'

Ejemplo 1 de 2

cerrado.py
import pandas as pd

pedidos = pd.Series(pd.to_datetime([
    "2026-03-30 18:05",
    "2026-03-31 00:00",
    "2026-03-31 09:15",
    "2026-03-31 21:40",
]))
de_marzo = pedidos[(pedidos >= "2026-03-01") & (pedidos <= "2026-03-31")]
print(len(de_marzo))

Adivinar está bien: se guarda tal como la escribiste para compararla. Solo tú y tu Maestro ven tus predicciones.

Ejemplo 2 de 2, se abre cuando expliques este

Haz tu predicción

Una fecha sola es la medianoche

Cuando comparas un timestamp con una fecha sin hora, la fecha vale lo mismo que su primer instante: '2026-03-31' es 2026-03-31 00:00:00. Con eso se explican tres errores comunes:

  • BETWEEN '2026-03-01' AND '2026-03-31' incluye sus dos extremos, pero el extremo final es la medianoche del 31. En pedidos cuenta 154 pedidos y 33,469 pesos. Marzo tuvo 159 pedidos y 34,630 pesos en UTC.
  • creado_utc = '2026-03-31' busca pedidos creados exactamente a las 00:00:00. Hubo 5 pedidos ese día y el filtro encuentra 0.
  • <= '2026-03-31 23:59:59' parece arreglarlo, pero deja fuera lo que pase después del último segundo entero, si tus datos guardan fracciones de segundo.

Si no ves por qué BETWEEN pierde el 31, pregúntale a tu Maestro con tus palabras.

El intervalo semiabierto

La forma que no falla es un intervalo semiabierto: desde el primer instante del periodo, incluido, hasta el primer instante del periodo siguiente, sin incluirlo.

creado_utc >= '2026-03-01' AND creado_utc < '2026-04-01'

Funciona igual para un día (>= '2026-03-31' AND < '2026-04-01'), una semana o un año, y no depende de cuántos días tiene el mes ni de cuántos decimales trae la hora.

Compara la columna con dos textos de fecha y une las condiciones con &, cada una entre paréntesis:

Python
marzo = data[(data["creado_utc"] >= "2026-03-01") & (data["creado_utc"] < "2026-04-01")]

Series.between("2026-03-01", "2026-03-31") tiene el mismo problema que BETWEEN: en pedidos cuenta 154.

SQL
SELECT count(*) AS pedidos, sum(total) AS total
FROM pedidos
WHERE creado_utc >= '2026-03-01'
  AND creado_utc < '2026-04-01';

Otra salida que funciona para días completos es quitarle la hora a la columna antes de comparar: creado_utc::DATE BETWEEN '2026-03-01' AND '2026-03-31' también cuenta 159.

Inténtalo

La consulta de abajo usa BETWEEN y pierde pedidos. Cámbiala por un intervalo semiabierto. Una buena respuesta tiene una fila: 159 pedidos y 34,630 pesos.

Cuenta los pedidos de marzo de 2026 (en UTC) y suma su total sin perder ningún pedido del día 31.

Tu turno

Cuenta los pedidos de marzo de 2026 (en UTC) y suma su total sin perder ningún pedido del día 31.

Tablas: pedidos (pedido_id, creado_utc, total)

pedidos · 304 filas

ColumnaTipo
pedido_idBIGINT
creado_utc Cuándo se hizo el pedido, en UTC, como lo guarda la tienda en línea.TIMESTAMP
total Total del pedido en pesos.BIGINT

Primeras filas

pedido_idcreado_utctotal
50012026-02-01T02:44:40Z89
50022026-02-01T02:54:59Z420
50032026-02-01T15:15:38Z89

Cada ejecución empieza con copias nuevas de las tablas del curso, así que puedes probar lo que quieras.

Listo para ejecutar tu consulta.

Ejecútalo tú

Inténtalo sin ayuda

Ahora en pandas: cuenta los pedidos del 31 de marzo de 2026, en UTC, y suma su total. Usa un intervalo semiabierto de un día. Una buena respuesta cuenta 5 pedidos. Si te sale 0, pégale tu código a tu Maestro.

Cuenta los pedidos del 31 de marzo de 2026 (en UTC) y suma su total, con un intervalo semiabierto.

Cuenta los pedidos del 31 de marzo de 2026 (en UTC) y suma su total, con un intervalo semiabierto.

Ejecuta tu código para ver lo que imprime y el valor de su última expresión. Cada ejecución empieza de nuevo.

Listo para ejecutar tu código.

Ejecuta tu código para ver su salida aquí.

Datos: pedidos-en-linea, 304 filas

Enter guarda una celda y Escape la deja como estaba. Deja una celda vacía para un valor faltante.

Los datos del ejercicio, "pedidos-en-linea". Tus cambios corren con tu código.
FilaQuitar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Página 1 de 16

Ejecútalo tú

Comprueba lo que sabes: ¿Cuál de estos filtros cuenta todos los pedidos del 15 de marzo de 2026, a cualquier hora?