Skip to content

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ía

Sumar 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.141592653589793

Redondear 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 flotantes

Error 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:

Reloj, fecha y cuenta regresiva

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 ​

  1. Muestra la fecha de hoy con el formato "lunes 19 de octubre" (sin año).
  2. Escribe esFinDeSemana(fecha) que devuelva true si es sábado o domingo.
  3. Una tienda entrega en 3 días hábiles (lunes a viernes). Escribe fechaEntrega(desde) que salte los fines de semana.
  4. Simula lanzar dos dados 1000 veces y cuenta cuántas veces la suma fue 7.
  5. 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) o Intl.DateTimeFormat; tiempo relativo con Intl.RelativeTimeFormat.
  • Guarda y envía fechas en ISO/UTC (toISOString).
  • Math.floor, ceil, round, max, min y random cubren el 90 % de los casos.
  • Para dinero usa centavos; para valores seguros usa crypto, no Math.random.

Siguiente: El DOM

Academia Web — aprende, copia y construye.