Módulo 5: Scheduling y Tiempo
Cálculos con Fechas en n8n (Luxon DateTime)
Descripción de la cápsula
n8n incluye Luxon como biblioteca de fechas — disponible en cualquier expression. Saber usar Luxon te permite operaciones tipo "calcular fecha N días atrás", "primer día del mes siguiente", "diferencia en días entre dos fechas", "formato legible humano".
Esta cápsula es una referencia práctica de Luxon enfocada en casos de negocio. No es exhaustiva — cubre el 80% que usarás.
Lo que vas a aprender
- ✅ Crear DateTime desde strings, ISO, Unix timestamps
- ✅ Formatear para output legible
- ✅ Sumar/restar unidades de tiempo
- ✅ Calcular diferencias entre fechas
- ✅ Manipular fechas (start/end of, set día, etc.)
- ✅ Comparar fechas
Crear DateTime
// Ahora (UTC)
DateTime.now()
// Ahora en una timezone
DateTime.now().setZone('America/Mexico_City')
// Desde ISO string
DateTime.fromISO('2026-05-11T14:30:00Z')
// Desde formato custom
DateTime.fromFormat('11/05/2026', 'dd/MM/yyyy')
// Desde Unix timestamp (segundos)
DateTime.fromSeconds(1778509800)
// Desde Unix timestamp (milisegundos)
DateTime.fromMillis(1778509800000)
Formatear para output
const dt = DateTime.now()
// ISO 8601 (default)
dt.toISO() // "2026-05-11T14:30:00.000+00:00"
// Formato custom
dt.toFormat('yyyy-MM-dd') // "2026-05-11"
dt.toFormat('dd/MM/yyyy') // "11/05/2026"
dt.toFormat('HH:mm:ss') // "14:30:00"
dt.toFormat('dd MMM yyyy') // "11 May 2026"
dt.toFormat('cccc, dd MMMM') // "Monday, 11 May" (English)
// Localizado (con setLocale)
dt.setLocale('es').toFormat('cccc, dd MMMM') // "lunes, 11 mayo" (Spanish)
Format tokens más usados
| Token | Significa | Ejemplo |
|---|---|---|
yyyy | Año 4 dígitos | 2026 |
yy | Año 2 dígitos | 26 |
MM | Mes 2 dígitos | 05 |
MMM | Mes abreviado | May |
MMMM | Mes completo | May / mayo |
dd | Día 2 dígitos | 11 |
EEEE | Día semana completo | Sunday / domingo |
EEE | Día semana abreviado | Sun / dom |
HH | Hora 24h | 14 |
hh | Hora 12h | 02 |
mm | Minutos | 30 |
ss | Segundos | 00 |
a | AM/PM | PM |
Sumar/restar tiempo
const dt = DateTime.now()
// Sumar
dt.plus({ days: 7 }) // 7 días en el futuro
dt.plus({ hours: 3 })
dt.plus({ months: 1 })
dt.plus({ weeks: 2 })
// Restar
dt.minus({ days: 7 }) // 7 días en el pasado
// Combinaciones
dt.plus({ months: 1, days: 2, hours: 3 })
Casos típicos
// Hace 30 días
DateTime.now().minus({ days: 30 }).toISO()
// En 2 semanas
DateTime.now().plus({ weeks: 2 }).toISO()
// Fin del trimestre actual
DateTime.now().endOf('quarter')
// Inicio del mes siguiente
DateTime.now().plus({ months: 1 }).startOf('month')
Calcular diferencias
const dt1 = DateTime.fromISO('2026-05-11')
const dt2 = DateTime.fromISO('2026-05-25')
// Diferencia en días
dt2.diff(dt1, 'days').days // 14
// En múltiples unidades
dt2.diff(dt1, ['days', 'hours']) // { days: 14, hours: 0 }
// Diferencia desde ahora
DateTime.now().diff(DateTime.fromISO('2026-01-01'), 'days').days
Casos típicos
// Días desde el registro
{{ DateTime.now().diff(DateTime.fromISO($json.registration_date), 'days').days }}
// Es del último mes?
{{ DateTime.now().diff(DateTime.fromISO($json.date), 'days').days < 30 }}
// Días hasta el fin de mes
{{ DateTime.now().endOf('month').diff(DateTime.now(), 'days').days }}
Manipular fechas
// Start/end of period
DateTime.now().startOf('day') // hoy 00:00:00
DateTime.now().endOf('day') // hoy 23:59:59
DateTime.now().startOf('month') // 1 del mes 00:00:00
DateTime.now().endOf('month') // último día del mes 23:59:59
DateTime.now().startOf('year') // 1 enero 00:00:00
DateTime.now().endOf('quarter')
// Setear partes específicas
DateTime.now().set({ hour: 9, minute: 0 }) // hoy a las 9:00:00
// Obtener partes
DateTime.now().year // 2026
DateTime.now().month // 5 (mayo)
DateTime.now().day // 11
DateTime.now().weekday // 1-7 (1=lunes, 7=domingo en ISO)
DateTime.now().hour // 14
Comparar fechas
const dt1 = DateTime.fromISO('2026-05-11')
const dt2 = DateTime.fromISO('2026-05-25')
dt1 < dt2 // true
dt1 > dt2 // false
dt1.equals(dt2) // false
// Métodos
dt1.startOf('day').equals(DateTime.now().startOf('day')) // ¿es hoy?
Casos de negocio comunes
Caso 1: "Hace más de 7 días desde X"
{{ DateTime.now().diff(DateTime.fromISO($json.date), 'days').days > 7 }}
Caso 2: "Fecha legible humano en español"
{{ DateTime.fromISO($json.date).setLocale('es').toFormat("EEEE dd 'de' MMMM 'de' yyyy") }}
// "lunes 11 de mayo de 2026"
Caso 3: "Próximo lunes"
{{ DateTime.now().plus({ days: (1 + 7 - DateTime.now().weekday) % 7 || 7 }).startOf('day') }}
Caso 4: "Es horario de oficina (9-18, L-V, en timezone X)"
{{
(() => {
const dt = DateTime.now().setZone('America/Mexico_City');
return dt.hour >= 9 && dt.hour < 18 && dt.weekday >= 1 && dt.weekday <= 5;
})()
}}
Caso 5: "Cuántos días hábiles entre 2 fechas"
{{
(() => {
let count = 0;
let current = DateTime.fromISO($json.start_date);
const end = DateTime.fromISO($json.end_date);
while (current <= end) {
if (current.weekday <= 5) count++;
current = current.plus({ days: 1 });
}
return count;
})()
}}
Trampas comunes
Trampa 1: Strings de fecha en formato no-ISO
Qué pasa: DateTime.fromISO('11/05/2026') falla porque no es ISO.
Cómo evitar: Usar DateTime.fromFormat('11/05/2026', 'dd/MM/yyyy').
Trampa 2: Timezones mezcladas en operaciones
Qué pasa: Comparas DateTime UTC con DateTime CDMX. Resultados raros.
Cómo evitar: Convertir ambos a la misma timezone antes de comparar.
Trampa 3: DST en fechas pasadas/futuras
Qué pasa: Calculas "1 año atrás". DST hace que sea 1 hora distinto al esperado.
Cómo evitar: Trabajar en UTC para cálculos, convertir a TZ para display.
Resumen
- Luxon es la biblioteca de fechas en n8n
- fromISO, fromFormat, now para crear
- toFormat para output legible
- plus/minus con objetos
{ days, hours, etc } - diff para diferencias entre fechas
- startOf/endOf para periodos
- setLocale('es') para format en español
- 3 trampas: strings no-ISO, TZ mezcladas, DST en cálculos largos
Lo que sigue: Business days y calendarios fiscales — patrones para días hábiles y holidays.
Creado: Mayo 11, 2026 Versión: 1.0