Home > Enterprise >  Getting date range based on date and hour
Getting date range based on date and hour

Time:11-03

I am trying to get individual dates ("2022-10-10") and hours ("2022-10-10T09") between an interval in UTC. I could get the individual dates by the following -

function getDatesInRange(startDate, endDate) {
    const date = new Date(startDate.getTime());

    const dates = [];

    while (date <= endDate) {
        const day = new Date(date).toISOString().split(':')[0].split('T')[0];
        dates.push(day);

        date.setDate(date.getDate()   1);
    }
    return dates;
}
console.log(getDatesInRange(new Date('2022-10-10T20:50:59.938Z'), new Date('2022-10-15T23:50:59.938Z')));

Hence, the above returns - ["2022-10-10", "2022-10-11", "2022-10-12", "2022-10-13", "2022-10-14", "2022-10-15"]

I also want to return the hours of the start and end date and the rest should be dates. So i want to get in return - ["2022-10-10T20", "2022-10-10T21", "2022-10-10T22", "2022-10-10T23" "2022-10-11", "2022-10-12", "2022-10-13", "2022-10-14", "2022-10-15T00", "2022-10-15T01"]

Here is what i have as of now -

function getHoursInRange(startDate, endDate) {
  let startDatePlusOne = new Date(startDate);
  startDatePlusOne.setDate(startDatePlusOne.getDate()   1);
  
  let endDateMinusOne = new Date(endDate);
  endDateMinusOne.setDate(endDateMinusOne.getDate() - 1);
  
  const date = new Date(startDate.getTime());
  
  console.log("Start date :", date);
  let dates = getDatesInRange(startDatePlusOne, endDateMinusOne);
  console.log("Only days : ", dates);
  
  startDatePlusOne.setHours(0);

    while (date < startDatePlusOne) {
        const day = new Date(date).toISOString().split(':')[0];
        dates.push(day);

        date.setHours(date.getHours()   1);
    }
    endDateMinusOne.setHours(23);
    const edate = endDateMinusOne.getTime();
    while (edate < endDate) {
        const day = new Date(edate).toISOString().split(':')[0];
        dates.push(day);

        date.setHours(date.getHours()   1);
    }
  return dates
}

For this use case, i am getting the days back excluding the start and end dates. But for getting each hour of start and end date it gets stuck somehow. Somehow i feel there is a better way to do this. Any ideas ?

CodePudding user response:

You can do it a simpler way by incrementing the timestamp by 30 minutes at a time, and keeping a note of all non-duplicate hour strings and date strings:

function getDatesInRange(startDate, endDate) {
  let h = new Set(), d = new Set(), t = [];
  for(let i=startDate.getTime(); i<endDate.getTime(); i =1000*1800) t.push(i);
  [...t, endDate.getTime()].forEach(i=>{
    let s = new Date(i).toISOString();
    [[s.split(':')[0], h], [s.split('T')[0], d]].forEach(([s,r])=>r.add(s));
  });
  let firstDate = [...d.values()][0], lastDate = [...d.values()].pop();
  return d.size===1 ? [...h.values()] : [
    ...[...h.values()].filter(v=>v.startsWith(firstDate)),
    ...[...d.values()].filter(v=>v!==firstDate && v!==lastDate),
    ...[...h.values()].filter(v=>v.startsWith(lastDate))];
}
console.log(getDatesInRange(
  new Date('2022-10-10T20:50:59.938Z'), new Date('2022-10-15T23:50:59.938Z')));

CodePudding user response:

dateRange constructs an array of Date objects corresponding to the supplied range, inclusive.

dayToString takes a date and creates an array of strings, one for each hour of the day between the specified UTC hour range, inclusive.

dateRangeToStrings accepts an array of dates and constructs an array of strings according to the rules laid-out in the question.

const twoDigit = (n) => String(n).padStart(2, '0')
const toISODateString = (date) => `${date.getUTCFullYear()}-${twoDigit(date.getUTCMonth()   1)}-${twoDigit(date.getUTCDate())}`
    
const dateRange = (start, end, curr = new Date(start)) => {
    const dates = []
    while (curr <= end) {
        dates.push(new Date(Date.UTC(curr.getUTCFullYear(), curr.getUTCMonth(), curr.getUTCDate())))
        curr.setUTCDate(curr.getUTCDate()   1)
    }
    return dates
}

const dayToString = (date, startUTCHour = 0, endUTCHour = 23) =>
    Object.keys([...Array(24)])
          .slice(startUTCHour, endUTCHour   1)
          .map((h)=>`${toISODateString(date)}T${twoDigit(h)}`)

const dateRangeToStrings = (arr, startUTCHour, endUTCHour) => {
    const beginning = dayToString(arr[0], startUTCHour)
    const middle = arr.slice(1, -1).map(toISODateString)
    const end = dayToString(arr[arr.length - 1], 0, endUTCHour)
    return beginning.concat(middle, end)
}

const getDatesInRange = (start, end) => 
    dateRangeToStrings(dateRange(start, end), 
                      start.getUTCHours(), 
                      end.getUTCHours())

console.log(getDatesInRange(new Date('2022-10-10T20:50:59.938Z'), 
                            new Date('2022-10-15T23:50:59.938Z')))

  • Related