Como formatar datas no objeto de data Javascript e trabalhar com a definição de intervalos entre eles?

Aug 21 2020

Estou fazendo um aplicativo de agendamento. O requisito é que o usuário insira dois intervalos de tempo e o aplicativo deve dividi-los em intervalos de 20 com 10 minutos de intervalo entre eles. Por exemplo, se eu inserir 15: 15-17: 15, ele deve me fornecer slots como: ['15: 15 ', '15: 35', '15: 45 ', '16: 55'].

Erros que estou enfrentando: a abordagem que estou usando funciona bem para definir intervalos, mas não é possível dar um intervalo de 10 minutos entre eles. Minha saída dá ["15:15", "15:35", "15:55", "16:15", "16:35", "16:55", "17:15"]. Além disso, se eu inserir o horário de término como 17:05, o resultado ainda dará a contagem final como 17:15.

Por fim, se os dois problemas acima forem resolvidos, ficaria grato se alguém pudesse me dizer como devo formatar a matriz de modo que possa obter o resultado como: ['15: 15-15: 35 ', '15: 45-16: 55 ']. TIA

    let date1 = new Date(2020, 8, 20, 15, 15);
    let date2 = new Date(2020, 8, 20, 17, 05);
    let slots = []
    if(date1 < date2){
      console.log((date2.getHours()*60 - date1.getHours()*60)/20)
      for(var i = 0; date1 < date2; i=20)
      {
        date1.setMinutes(date1.getMinutes()+i)
        slots.push(date1.getHours() + ':' + date1.getMinutes());
      }
      console.log(slots)
    }
    else{
      console.log('End time should be greater than start time')
    }

Respostas

1 OvinusReal Aug 21 2020 at 02:16

Isso deve resolver o problema:

const dateToString = date => date.getHours() + ':' + (date.getMinutes() + '').padStart(2, '0')

const date1 = new Date(2020, 8, 20, 15, 15);
const date2 = new Date(2020, 8, 20, 17, 05);

function getIntervals(date1, date2) {
    date1 = new Date(date1.getTime()) // so we don't mutate date1

    const intervalLength = 20, breakLength = 10, intervals = []
    let interval

    while (date1 < date2) {
        interval && intervals.push(interval)

        interval = [intervalLength, breakLength].map(len => {
            const str = dateToString(date1)
            date1.setMinutes(date1.getMinutes() + len)
            return str
        }).join('-') // - separator
    }

    return intervals
}

console.log(getIntervals(date1, date2))

dateToStringconverte um objeto Date em um formato hh: mm, preenchendo o componente de minuto com zeros, se necessário. Para obter os intervalos, alternamos comprimentos de tempo de intervalLength e breakLength e transferimos cada intervalo gerado para nosso array. Em seguida, retornamos o intervalo.

RobG Aug 21 2020 at 05:10

O código no OP não parece estar dividindo o tempo corretamente ou permitindo os intervalos entre os períodos.

O tempo entre as duas datas deve ser dividido em n períodos com n-1 intervalos de 10 minutos entre eles. Subtrair uma data da outra dará a diferença de tempo em milissegundos, então ele precisa ser dividido nos períodos e intervalos necessários, por exemplo

/**
 * @param {Date} start - start date and time
 * @param {Date} end - end date and time
 * @param {number} periods - number of periods
 * @param {number} interval - interval between periods in minutes
 * @returns {Array} array of perids with interval gap between
 *   in format ['HH:mm - HH:mm', ...]
 */
function getSlots(start, end, periods, interval) {
  // Function to format period timestamp
  function f(d) {
    return ('' + d.getHours()).padStart(2, '0') + ':' + ('' + d.getMinutes()).padStart(2, '0');
  }
  let slots = [];
  let diff = end - start;
  if (diff < 0) return 'End must be after start';
  // Get length of interval in ms
  let intLength = interval * 6e4;
  // Get total length of intervals in ms
  let intTotal = (periods - 1) * intLength;
  // Get length of each period in ms
  let periodLength = (diff - intTotal) / periods;
  
  // Generate periods
  for (let e, s = new Date(start), i = periods; i > 0; i--) {
    // Copy start to get end and add length of period
    e = new Date(+s + periodLength);
    // Write period to slots array
    slots.push(f(s) + '-' + f(e));
    // Increment s to start of next period
    s.setMilliseconds(s.getMilliseconds() + periodLength + intLength);
  }
  return slots;
}

let date1 = new Date(2020, 8, 20, 15, 15);
let date2 = new Date(2020, 8, 20, 17,  5);

console.log(getSlots(date1, date2, 2, 10));

Observe que isso preenche totalmente o tempo permitido, não há intervalo nas extremidades. Além disso, os tempos são truncados para minutos inteiros, portanto, pode parecer não ter exatamente o mesmo número de minutos ou ser igual.