Estoy tratando de hacer un temporizador de cuenta regresiva de bucle infinito en JavaScript. Puedo hacer que las cuentas regresivas funcionen según lo previsto, pero no puedo hacer que se reinicien correctamente una vez que llegan a 0 / van por debajo de 0.

Debería haber especificado, pido disculpas, por el primer temporizador "mcReset". Necesito restablecer la fecha a 7 días desde la fecha originalmente especificada cuando el temporizador llega a 0.

Para el segundo temporizador "onyReset" necesito restablecer la fecha a 5 días desde la fecha especificada originalmente cuando el temporizador llega a 0.

Entonces, por ejemplo, mcReset (14 de octubre 9:28:00) se convertiría en 21 de octubre 9:28:00 y onyReset (17 de octubre de 2019 12:00:00) se convertiría en 22 de octubre de 2019 12:00:00 y la cuenta regresiva sería bucle infinito de eso.

No estoy muy familiarizada con JavaScript, por lo que se agradece cualquier ayuda :)

Aquí está el código:

// Set the date we're counting down to
var mcReset = new Date("Oct 14, 2019 9:28:00").getTime();
var onyReset = new Date("Oct  17, 2019 12:00:00").getTime();

// Update the count down every 1 second
var x = setInterval(function() {

  // Get today's date and time
  var now = new Date().getTime();
    
  // Find the distance between now and the count down date
  var distance = mcReset - now;
  var onyDistance = onyReset - now;
    
  // Time calculations for days, hours, minutes and seconds
  var mcDays = Math.floor(distance / (1000 * 60 * 60 * 24));
  var onyDays = Math.floor(onyDistance / (1000 * 60 * 60 * 24));
  var mcHours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var onyHours = Math.floor((onyDistance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var mcMinutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
  var onyMinutes = Math.floor((onyDistance % (1000 * 60 * 60)) / (1000 * 60));
  var mcSeconds = Math.floor((distance % (1000 * 60)) / 1000);
  var onySeconds = Math.floor((onyDistance % (1000 * 60)) / 1000);
    
  // Output the result in an element with id="demo"
  document.getElementById("demo").innerHTML = mcDays + "d " + mcHours + "h "
  + mcMinutes + "m " + mcSeconds + "s ";
  document.getElementById("ony").innerHTML = onyDays + "d " + onyHours + "h "
  + onyMinutes + "m " + onySeconds + "s ";
    
  // If the count down is over, reset
  if (distance < 0) {
  	// do something here?
	// not sure what
  }
}, 1000);
p {
  text-align: center;
  font-size: 60px;
  margin-top: 0px;
}
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>

<p id="demo"></p>
<p id="ony"></p>

</body>
</html>
-1
Bob G 14 oct. 2019 a las 16:33

3 respuestas

La mejor respuesta

La clave es asegurarse de que cada cuenta regresiva tenga la marca de tiempo objetivo correcta dentro de la función de intervalo que actualiza la página. Si la fecha de la cuenta regresiva ya está en el pasado, agregue el intervalo de cuenta regresiva; de esa manera, el tiempo restante saltará sin problemas a la cuenta regresiva para la siguiente marca de tiempo.

Aquí hay una forma de hacer esto:

const DAYS = 24 * 3600 * 1000;

const countdowns = [{
    id: "mcReset",
    timestamp: new Date("Oct 14, 2019 9:28:00").getTime(),
    interval: 7 * DAYS
  },
  {
    id: "onyReset",
    timestamp: new Date("Oct  17, 2019 12:00:00").getTime(),
    interval: 5 * DAYS
  },
  {
    id: "demo",
    timestamp: new Date(new Date().getTime() + 5000).getTime(),
    interval: 5000
  }
];

setInterval(() => {
  const now = new Date().getTime();
  countdowns.forEach(c => {
    while (c.timestamp < now) c.timestamp += c.interval; // set target to future date
    const tSecs = Math.floor((c.timestamp - now) / 1000);
    const secs = tSecs % 60;
    const tMins = (tSecs - secs) / 60;
    const mins = tMins % 60;
    const tHours = (tMins - mins) / 60;
    const hours = tHours % 24;
    const days = (tHours - hours) / 24;
    document.getElementById(c.id).textContent = `${days}d ${hours}h ${mins}m ${secs}s`;
  });
}, 1000);
p {
  text-align: center;
  font-size: 200%;
  margin-top: 0px;
}
<p id="mcReset"></p>
<p id="onyReset"></p>
<p id="demo"></p>
0
Chris G 14 oct. 2019 a las 14:38

Por lo tanto, agregue el número de días a la cadena y actualice las variables globales con los nuevos valores.

function addDaysGetTime(date, numOfDays) {
  var date = new Date(date);
  date.setDate(date.getDate() + numOfDays);
  return date.getTime()
}

var mcReset = new Date("Oct 14, 2019 9:28:00").getTime();
var onyReset = new Date("Oct  17, 2019 12:00:00").getTime();
console.log("before", mcReset, onyReset)


// if( distance < 0) {
  mcReset = addDaysGetTime(mcReset, 7)
  onyReset = addDaysGetTime(onyReset, 5)
// }

   console.log("after", mcReset, onyReset)

Técnicamente ni siquiera necesita usar métodos de fecha. Solo necesita agregar milisegundos a los números.

// if( distance < 0) {
  mcReset += 604800000
  onyReset += 432000000
// }
0
epascarello 14 oct. 2019 a las 14:27

He refactorizado tu código un poco.

Aquí hay una función que cuenta regresivamente hasta una fecha específica, y cuando se hace, elimina esa cuenta regresiva y se llama nuevamente con una nueva fecha:

// Helper function to get the current date and add 10 seconds on top of it
const get10SecsInFuture = () => {
  // Set the date we're counting down to
  let d = new Date();

  // Add one minute to date
  d.setTime(d.getTime() + 1000 * 10);
  
  return d;
}

// Make countDown a function
const countDown = (onyReset) => {
  let countDownHandle = setInterval(() => {

    // Get today's date and time
    let now = new Date().getTime();

    // Find the distance between now and the count down date
    let onyDistance = onyReset - now;

    // Time calculations for days, hours, minutes and seconds
    let onyDays = Math.floor(onyDistance / (1000 * 60 * 60 * 24));
    let onyHours = Math.floor((onyDistance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    let onyMinutes = Math.floor((onyDistance % (1000 * 60 * 60)) / (1000 * 60));
    let onySeconds = Math.floor((onyDistance % (1000 * 60)) / 1000);

    // Output the result in an element with id="demo"
    document.getElementById("ony").innerHTML = onyDays + "d " + onyHours + "h "
    + onyMinutes + "m " + onySeconds + "s ";

    // If the count down is over, reset
    if (onyDistance <= 0) {
      clearInterval(countDownHandle);
      countDown(get10SecsInFuture());
    }
  }, 300);
}

countDown(get10SecsInFuture());
p {
  text-align: center;
  font-size: 60px;
  margin-top: 0px;
}
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>

<p id="ony"></p>

</body>
</html>
0
MauriceNino 14 oct. 2019 a las 13:49