Pregunta 1¿Qué pasa si declaras let count = 0; dentro de la función que pasas a setInterval e intentas detenerla cuando count llegue a 3?
Temporizadores y fechas — setTimeout / Date / Intl
setTimeout y setInterval y cómo detenerlos, los meses de Date que empiezan en 0, Intl.DateTimeFormat y los días entre dos fechas.
Si el código solo avanza de arriba abajo, no puedes cerrar un aviso a los 3 segundos ni descontar cada segundo el tiempo que queda. Y mientras una fecha sea solo un texto, tampoco puedes mostrar qué día de la semana cae ni contar los días que faltan para una fecha límite.
En este artículo verás setTimeout y setInterval, que crean temporizadores, y Date e Intl.DateTimeFormat, que trabajan con fechas y horas.
Programar una llamada para después — setTimeout y clearTimeout
Imagina que un sitio para compartir fotos muestra el aviso «Subida completada» y quieres cerrarlo a los 3 segundos. El código que avanza de arriba abajo no tiene forma de decir «espera 3 segundos y luego sigue», y si haces tiempo con un for vacío, la página deja de responder a los clics y de actualizarse mientras dura el bucle.
setTimeout(función, milisegundos) solo programa la llamada y la ejecución pasa de inmediato a la línea siguiente. Devuelve un ID de temporizador, igual que el que usaste para el tiempo de espera de fetch, y si pasas ese ID a clearTimeout, la llamada se cancela.
// Devuelve una Promise que pasa a fulfilled pasados ms milisegundos (el delay del artículo de Promise, sin value)
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// Programa el cierre del aviso en 100ms y sigue enseguida (en una página real, unos 3000ms)
setTimeout(() => console.log("Aviso cerrado"), 100); // Aviso cerrado (2.º)
console.log("Subida completada"); // Subida completada (1.º)
// El usuario salió de la página, así que se cancelan las recomendaciones. No se llama ni a los 100ms
const recommendTimer = setTimeout(() => console.log("Mostrando fotos recomendadas"), 100);
clearTimeout(recommendTimer);
// No pasa de esta línea hasta que transcurren 200ms
await delay(200);
console.log("Pasaron 200ms"); // Pasaron 200ms (3.º)
Una función programada puede ejecutarse cuando tu código ya llegó a la última línea. Para ver su salida en la consola de los ejercicios, termina el código con una línea que espere, como await delay(…), igual que en el artículo de Promise.
Detener una repetición — setInterval y clearInterval
Ahora quieres mostrar los segundos que faltan para que termine una oferta, descontando uno cada segundo. setTimeout llama a la función programada una sola vez, así que para repetir, la función tendría que volver a programarse en cada llamada, y la condición para detenerse quedaría mezclada en ese mismo código.
setInterval (una función que llama a otra función una y otra vez, cada cierto número de milisegundos) sigue llamándola hasta que pasas a clearInterval el ID de temporizador que devolvió.
Para ejecutar la línea siguiente solo cuando termine la repetición, envuelve todo en una Promise y llama a resolve justo después de clearInterval, dentro del mismo if.
// Descuenta 1 segundo del tiempo restante cada 100ms (cada 1000ms en una página real)
function startCountdown(seconds) {
return new Promise((resolve) => {
let remaining = seconds; // Fuera de la función que se llama, para conservar el valor entre llamadas
const timerId = setInterval(() => {
remaining -= 1;
console.log(`Quedan ${remaining} s`); // Quedan 2 s → Quedan 1 s → Quedan 0 s
if (remaining === 0) {
clearInterval(timerId); // Se detiene en la llamada que llega a 0 (para entonces timerId ya tiene su valor)
resolve(); // Avisa a la línea del await de que terminó
}
}, 100);
});
}
await startCountdown(3);
console.log("La oferta terminó"); // La oferta terminó
- No pasa a la línea siguiente hasta que la Promise devuelta pasa a fulfilled
La oferta terminóse muestra después de resolve
let remaining = seconds— se crea una sola vez aquí, con el valor 3const timerId = setInterval(...)— el ID que pasas para detenerlo
remaining -= 1— resta 1 a la variable externa: 2 → 1 → 0- En la llamada que llega a 0,
clearInterval(timerId)yresolve()
Si mueves let remaining = seconds dentro de la función que se llama, vuelve a empezar en 3 en cada llamada y nunca baja de 2, así que no se llega a llamar ni a clearInterval ni a resolve. Pasados 15 segundos sin avanzar, la consola de los ejercicios indica que la ejecución superó el tiempo límite.
Una repetición que no detienes se cuela en las siguientes ejecuciones
La consola de los ejercicios usa la misma página para todas las ejecuciones de este artículo. Si una ejecución termina sin llamar a clearInterval, esa función se sigue llamando hasta que recargas la página, y su salida se mezcla con el resultado de los ejercicios que ejecutes después y que esperen con await, así que incluso el código correcto se marca como incorrecto. Si te pasa, recarga la página del artículo.
Convertir una fecha en texto para mostrar — getMonth e Intl
Supón que una lista de videos muestra la fecha de publicación en la forma «mié, 2 de septiembre de 2026». Si sacas el mes con slice de un texto de la API como "2026-09-02T09:00:00", obtienes la cadena "09", y como el día de la semana no aparece en ninguna parte, no puedes deducirlo solo a partir del texto.
Date (un objeto integrado que representa una fecha y hora) lee "2026-09-02T09:00:00" como las 9:00 a.m. en la zona horaria del dispositivo (la hora local de una región, definida por su diferencia con la hora de referencia UTC), y sus métodos que empiezan por get devuelven el mes, el día de la semana, etc., como números.
Intl.DateTimeFormat (una clase que convierte fechas y horas en texto según el idioma) se crea pasándole una configuración regional como "es-MX" (español de México).
const publishedAt = new Date("2026-09-02T09:00:00");
// Los métodos que empiezan por get devuelven números. En los meses, enero es 0; en los días de la semana, domingo es 0
console.log(publishedAt.getMonth(), publishedAt.getDate(), publishedAt.getDay()); // 8 2 3
// Crea un formateador pasando el idioma y el estilo de cada parte que quieres mostrar
const dateFormat = new Intl.DateTimeFormat("es-MX", {
year: "numeric", // Año como número
month: "long", // Mes con su nombre, como "septiembre"
day: "numeric", // Día como número
weekday: "short", // Día de la semana con su nombre corto
});
console.log(dateFormat.format(publishedAt)); // mié, 2 de septiembre de 2026
console.log(new Intl.DateTimeFormat("es-MX", { hour: "numeric", minute: "2-digit" }).format(publishedAt)); // 9:00 a.m.
// Un texto sin hora se lee como las 0:00 UTC
const dateOnly = new Date("2026-09-02");
console.log(dateOnly.getDate()); // 2 en Japón, 1 en Nueva York (8:00 p.m. del día anterior)
En zonas horarias por delante de UTC, como Japón, sigues obteniendo 2, así que el problema pasa desapercibido con facilidad. Cuando la API envía un texto solo con la fecha, agrégale "T00:00:00" antes de pasarlo a new Date para que se lea como las 0:00 en hora local. La tabla siguiente resume lo que devuelven los métodos get para publishedAt.
| Método | En publishedAt | Para mostrarlo |
|---|---|---|
| getFullYear() | 2026 | Úsalo tal cual |
| getMonth() | 8 | Enero es 0: suma 1 y da 9 |
| getDate() | 2 | Empieza en 1: úsalo tal cual |
| getDay() | 3 | Domingo es 0: 3 es miércoles |
| getHours() | 9 | Formato de 24 h, 0–23 |
Contar los días hasta una fecha límite — restar fechas
El sitio de una biblioteca muestra cuántos días faltan para devolver un libro. Si restas solo los números del día, un libro prestado el 2 de septiembre que vence el 3 de octubre da 3 - 2 = 1 día, porque no se cuentan los días de septiembre que hay en medio.
Por dentro, un Date es un número: los milisegundos transcurridos desde las 0:00 UTC del 1 de enero de 1970. Restar un Date a otro da la diferencia en milisegundos, así que al dividirla entre los milisegundos de un día, 24 * 60 * 60 * 1000, obtienes el número de días.
new Date(año, mes, día) crea las 0:00 en hora local de ese día, y aquí también los meses se cuentan desde 0.
// Milisegundos de un día (24 horas × 60 minutos × 60 segundos × 1000)
const DAY_MS = 24 * 60 * 60 * 1000;
// Fecha de préstamo y fecha límite. Al crearlas con números, los meses también se cuentan desde 0
const borrowedAt = new Date(2026, 8, 2); // 2 de septiembre de 2026
const dueDate = new Date(2026, 9, 3); // 3 de octubre de 2026
// Restar un Date a otro da la diferencia en milisegundos
const diffMs = dueDate - borrowedAt;
console.log(Math.round(diffMs / DAY_MS)); // 31
// Si pasas 31, un día que septiembre no tiene, no hay error: pasa al mes siguiente
const overflowDate = new Date(2026, 8, 31);
console.log(overflowDate.getMonth() + 1, overflowDate.getDate()); // 10 1
Se redondea con Math.round por el horario de verano (adelantar los relojes una hora durante el verano). Donde se aplica, algunos días duran 23 o 25 horas, así que la división no siempre da un número entero (puede salir algo como 30.958…). En lugares sin horario de verano, como Japón, la división siempre es exacta, así que es fácil olvidar el redondeo.
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 2¿Qué devuelve new Date("2026-09-02T09:00:00").getMonth()?
Pregunta 3¿Qué devuelve getDate() en un Date creado con new Date(2026, 8, 31)?