Tema
Fechas y Math
Reservaciones, fechas de entrega, "publicado hace 3 días", cuentas regresivas para una promoción, descuentos redondeados, sorteos... Casi cualquier proyecto para un cliente necesita trabajar con fechas y cálculos numéricos. En esta lección dominarás el objeto Date, la API Intl para mostrar fechas en español y el objeto Math.
Concepto
Date
Internamente, una fecha en JavaScript es un solo número: los milisegundos transcurridos desde el 1 de enero de 1970 a las 00:00 UTC (la "época Unix"). Todo lo demás (año, mes, día, hora) se calcula a partir de ese número. Por eso restar dos fechas te da milisegundos.
Math
Math es una "caja de herramientas" con constantes y funciones matemáticas: redondear, máximos, mínimos, potencias y números aleatorios. No se crea con new; se usa directamente: Math.round(4.6).
Crear fechas
js
// Fecha y hora actuales
const ahora = new Date();
// A partir de un string ISO (el formato más seguro)
const lanzamiento = new Date('2026-12-24T18:00:00'); // hora local
const utc = new Date('2026-12-24T18:00:00Z'); // la Z indica UTC
// A partir de componentes: año, MES (0-11), día, hora, minuto
const navidad = new Date(2026, 11, 25, 0, 0); // ¡11 = diciembre!
// A partir de milisegundos
const desdeTimestamp = new Date(1767225600000);
// El timestamp actual (sin crear un objeto)
const ms = Date.now();Error común: los meses empiezan en 0
En new Date(año, mes, día), enero es 0 y diciembre es 11. En cambio, los días sí empiezan en 1. Es la fuente de bugs más clásica con fechas. Cuando puedas, usa strings ISO ('2026-03-15'), donde marzo sí es 03.
Error común: '2026-03-15' sin hora se interpreta en UTC
new Date('2026-03-15') crea la fecha a medianoche UTC, que en México es el día anterior a las 18:00. Si muestras sólo la fecha, verás "14 de marzo". Para fechas locales usa new Date('2026-03-15T00:00:00') o new Date(2026, 2, 15).
Leer y modificar partes de una fecha
js
const fecha = new Date('2026-10-18T14:35:20');
fecha.getFullYear(); // 2026
fecha.getMonth(); // 9 (octubre, recuerda: base 0)
fecha.getDate(); // 18 (día del mes)
fecha.getDay(); // 0 (día de la semana: 0 = domingo ... 6 = sábado)
fecha.getHours(); // 14
fecha.getMinutes(); // 35
fecha.getTime(); // milisegundos desde 1970
// Modificar (muta el objeto)
fecha.setDate(fecha.getDate() + 7); // sumar 7 días (cambia de mes solo si hace falta)
fecha.setHours(0, 0, 0, 0); // inicio del díaSumar días sin mutar
js
function sumarDias(fecha, dias) {
const copia = new Date(fecha); // copiamos para no modificar la original
copia.setDate(copia.getDate() + dias);
return copia;
}
const hoy = new Date();
const entrega = sumarDias(hoy, 5);Mostrar fechas en español
Olvídate de armar arrays con nombres de meses. toLocaleDateString e Intl.DateTimeFormat lo hacen por ti:
js
const fecha = new Date('2026-10-18T14:35:00');
fecha.toLocaleDateString('es-MX');
// '18/10/2026'
fecha.toLocaleDateString('es-MX', {
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
});
// 'domingo, 18 de octubre de 2026'
fecha.toLocaleTimeString('es-MX', { hour: '2-digit', minute: '2-digit' });
// '02:35 p.m.'
// Formateador reutilizable
const formatoCorto = new Intl.DateTimeFormat('es-MX', {
day: 'numeric', month: 'short', year: 'numeric'
});
formatoCorto.format(fecha); // '18 oct 2026'
// Estilos predefinidos
new Intl.DateTimeFormat('es-MX', { dateStyle: 'full', timeStyle: 'short' }).format(fecha);
// 'domingo, 18 de octubre de 2026, 14:35'Para guardar o enviar a una API: ISO
js
new Date().toISOString(); // '2026-10-18T20:35:00.000Z' (siempre UTC)
// Sólo la fecha local en formato AAAA-MM-DD (útil para <input type="date">)
function aFechaInput(fecha) {
const a = fecha.getFullYear();
const m = String(fecha.getMonth() + 1).padStart(2, '0');
const d = String(fecha.getDate()).padStart(2, '0');
return `${a}-${m}-${d}`;
}Diferencia entre fechas
Como las fechas son números, restarlas da milisegundos:
js
const MS_POR_DIA = 1000 * 60 * 60 * 24;
function diasEntre(inicio, fin) {
return Math.round((fin - inicio) / MS_POR_DIA);
}
diasEntre(new Date('2026-10-18T00:00:00'), new Date('2026-12-25T00:00:00')); // 68"Hace 5 minutos": tiempo relativo
Intl.RelativeTimeFormat genera frases como "hace 3 días" o "dentro de 2 horas":
js
const rtf = new Intl.RelativeTimeFormat('es', { numeric: 'auto' });
function tiempoRelativo(fecha) {
const segundos = Math.round((fecha - Date.now()) / 1000);
const unidades = [
['year', 60 * 60 * 24 * 365],
['month', 60 * 60 * 24 * 30],
['day', 60 * 60 * 24],
['hour', 60 * 60],
['minute', 60],
['second', 1]
];
for (const [unidad, valor] of unidades) {
if (Math.abs(segundos) >= valor || unidad === 'second') {
return rtf.format(Math.round(segundos / valor), unidad);
}
}
}
tiempoRelativo(new Date(Date.now() - 5 * 60 * 1000)); // 'hace 5 minutos'
tiempoRelativo(new Date(Date.now() - 86400000)); // 'ayer'Calcular la edad
js
function calcularEdad(fechaNacimiento) {
const hoy = new Date();
const nac = new Date(fechaNacimiento);
let edad = hoy.getFullYear() - nac.getFullYear();
const yaCumplio =
hoy.getMonth() > nac.getMonth() ||
(hoy.getMonth() === nac.getMonth() && hoy.getDate() >= nac.getDate());
if (!yaCumplio) edad--;
return edad;
}Buena práctica
Para apps con muchas operaciones de fechas (zonas horarias, calendarios, recurrencias) usa una librería ligera como date-fns o Day.js. Y guarda siempre las fechas en tu base de datos en UTC/ISO; conviértelas a hora local sólo al mostrarlas.
Math
js
Math.round(4.5); // 5 redondeo normal
Math.floor(4.9); // 4 hacia abajo
Math.ceil(4.1); // 5 hacia arriba
Math.trunc(-4.7); // -4 quita decimales
Math.abs(-10); // 10 valor absoluto
Math.max(3, 9, 2); // 9
Math.min(...[3, 9, 2]); // 2 (con spread para arrays)
Math.pow(2, 10); // 1024 (o 2 ** 10)
Math.sqrt(81); // 9
Math.PI; // 3.141592653589793Redondear a decimales
js
// Redondear a 2 decimales y seguir teniendo un número
const redondear = (n, decimales = 2) => {
const factor = 10 ** decimales;
return Math.round((n + Number.EPSILON) * factor) / factor;
};
redondear(1.005); // 1.01
(1.005).toFixed(2); // '1.00' ← toFixed devuelve string y puede fallar con flotantesError común: decimales flotantes
0.1 + 0.2 da 0.30000000000000004. Las computadoras representan decimales en binario y algunos no son exactos. Para dinero, trabaja en centavos (enteros) y divide entre 100 sólo al mostrar: 14999 centavos → $149.99.
Números aleatorios
Math.random() devuelve un decimal entre 0 (incluido) y 1 (excluido).
js
// Entero aleatorio entre min y max (ambos incluidos)
function aleatorio(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
aleatorio(1, 6); // dado: 1..6
// Elemento aleatorio de un array
const premios = ['10% desc.', 'Envío gratis', 'Sigue participando'];
const premio = premios[Math.floor(Math.random() * premios.length)];
// Color hexadecimal aleatorio
const colorAleatorio = () =>
'#' + Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0');
// Barajar un array (algoritmo Fisher-Yates)
function barajar(array) {
const copia = [...array];
for (let i = copia.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[copia[i], copia[j]] = [copia[j], copia[i]];
}
return copia;
}Seguridad
Math.random() no es seguro para contraseñas, tokens o códigos de verificación. Para eso usa crypto.getRandomValues() o crypto.randomUUID():
js
const id = crypto.randomUUID(); // 'b3f1c8e2-...'Demo en vivo
Reloj en tiempo real con setInterval, la fecha en español con Intl y una cuenta regresiva hacia una fecha que tú eliges:
La lógica clave de la cuenta regresiva:
js
function tiempoRestante(destino) {
const diff = Math.max(0, destino - Date.now()); // nunca negativo
return {
dias: Math.floor(diff / 86400000),
horas: Math.floor((diff / 3600000) % 24),
minutos: Math.floor((diff / 60000) % 60),
segundos: Math.floor((diff / 1000) % 60),
terminado: diff === 0
};
}Ejercicios
- Muestra la fecha de hoy con el formato
"lunes 19 de octubre"(sin año). - Escribe
esFinDeSemana(fecha)que devuelvatruesi es sábado o domingo. - Una tienda entrega en 3 días hábiles (lunes a viernes). Escribe
fechaEntrega(desde)que salte los fines de semana. - Simula lanzar dos dados 1000 veces y cuenta cuántas veces la suma fue 7.
- Escribe
aplicarDescuento(precio, porcentaje)que redondee a 2 decimales y nunca devuelva menos de 0.
Ver solución
js
// 1
new Date().toLocaleDateString('es-MX', { weekday: 'long', day: 'numeric', month: 'long' });
// 2
const esFinDeSemana = (fecha) => [0, 6].includes(fecha.getDay());
// 3
function fechaEntrega(desde, diasHabiles = 3) {
const fecha = new Date(desde);
let restantes = diasHabiles;
while (restantes > 0) {
fecha.setDate(fecha.getDate() + 1);
if (!esFinDeSemana(fecha)) restantes--;
}
return fecha;
}
// 4
const dado = () => Math.floor(Math.random() * 6) + 1;
let sietes = 0;
for (let i = 0; i < 1000; i++) {
if (dado() + dado() === 7) sietes++;
}
console.log(`Salió 7: ${sietes} veces (~${(sietes / 10).toFixed(1)} %)`); // ≈ 16.7 %
// 5
function aplicarDescuento(precio, porcentaje) {
const final = precio * (1 - porcentaje / 100);
return Math.max(0, Math.round(final * 100) / 100);
}Resumen
- Una fecha es un número de milisegundos desde 1970; restar fechas da milisegundos.
- Los meses en
new Date(a, m, d)van de 0 a 11. - Muestra fechas con
toLocaleDateString('es-MX', opciones)oIntl.DateTimeFormat; tiempo relativo conIntl.RelativeTimeFormat. - Guarda y envía fechas en ISO/UTC (
toISOString). Math.floor,ceil,round,max,minyrandomcubren el 90 % de los casos.- Para dinero usa centavos; para valores seguros usa
crypto, noMath.random.
Siguiente: El DOM