Funciones de fecha: calcular periodos y construir límites seguros

Las fechas representan instantes o periodos, no textos con un formato visual. Para sumar días, medir diferencias, obtener fin de mes o construir una fecha utilizamos funciones temporales y tipos apropiados.

Una de las decisiones más importantes es expresar correctamente los rangos cuando la columna también contiene hora.

Funciones principales

Función Uso
DATEADD Suma o resta una cantidad de unidades
DATEDIFF Cuenta límites de unidad atravesados
DATEFROMPARTS Construye una fecha con año, mes y día
EOMONTH Devuelve el último día de un mes

Ejemplo: sumar un periodo

SELECT
    p.IdPedido,
    p.FechaPedido,
    DATEADD(DAY, 5, p.FechaPedido) AS FechaEstimada
FROM dbo.Pedido AS p;

El primer argumento indica la unidad; el segundo, la cantidad. Una cantidad negativa resta tiempo.

Medir una diferencia

SELECT
    c.IdCliente,
    c.FechaRegistro,
    DATEDIFF(DAY, c.FechaRegistro, SYSDATETIME()) AS DiasDesdeRegistro
FROM dbo.Cliente AS c;

DATEDIFF cuenta cuántos límites de día se atravesaron. No calcula una duración decimal exacta. Dos instantes separados por pocos segundos pueden producir 1 día si se encuentran a lados distintos de la medianoche.

Construir el inicio y final de un mes

DECLARE @Anio INT = 2026;
DECLARE @Mes INT = 3;

SELECT
    DATEFROMPARTS(@Anio, @Mes, 1) AS InicioMes,
    EOMONTH(DATEFROMPARTS(@Anio, @Mes, 1)) AS FinMes;

Las variables creadas mediante DECLARE se explican de forma independiente en la ficha sobre variables.

DATEFROMPARTS evita depender del idioma o formato regional de una cadena.

Filtrar un rango que contiene hora

Para consultar todos los pedidos de marzo utilizamos un límite inicial inclusivo y uno final exclusivo:

DECLARE @Desde DATE = '2026-03-01';
DECLARE @Hasta DATE = '2026-04-01';

SELECT
    p.IdPedido,
    p.FechaPedido,
    p.Estado
FROM dbo.Pedido AS p
WHERE p.FechaPedido >= @Desde
  AND p.FechaPedido < @Hasta
ORDER BY p.FechaPedido;

Esta forma incluye cualquier precisión de hora dentro de marzo. Evita escribir un final como 23:59:59, que puede omitir valores con mayor precisión.

Calcular el siguiente mes

Cuando solo recibimos una fecha inicial, el límite exclusivo puede derivarse:

DECLARE @InicioMes DATE = '2026-03-01';
DECLARE @InicioSiguienteMes DATE = DATEADD(MONTH, 1, @InicioMes);

Qué conviene comprobar

Debemos distinguir DATE, DATETIME, DATETIME2 y valores con zona u offset. SYSDATETIME() utiliza el reloj local del servidor; no representa automáticamente la zona del usuario.

También evitamos convertir la columna a texto dentro del filtro. Comparar un rango temporal conserva el significado del dato y normalmente ofrece mejores posibilidades de utilizar un índice.

Relacionado con

  • Conversiones: interpretan o presentan fechas cuando realmente necesitamos texto.
  • WHERE: expresa rangos mediante límites inclusivos y exclusivos.
  • ORDER BY: organiza cronológicamente los resultados.
  • Funciones de ventana: permiten acumulados y comparaciones temporales.