Ojhey
Ojhey

Reputation: 13

Filter an array of ISO date by days of the week in javascript

I have an array of ISO dates I'm trying to sort and get only the next seven days from it

Here is the sample

Here is the sample code

daysdata = [{time: '2022-01-23T11:00:00Z', data: {…}},   
     {time: '2022-01-23T12:00:00Z', data: {…}},   
     {time: '2022-01-24T11:00:00Z', data: {…}},   
     {time: '2022-01-24T12:00:00Z', data: {…}},   
     {time: '2022-01-24T17:00:00Z', data: {…}},   
     {time: '2022-01-24T23:00:00Z', data: {…}},   
     {time: '2022-01-25T00:00:00Z', data: {…}},   
     {time: '2022-01-25T04:00:00Z', data: {…}},   
     {time: '2022-01-25T05:00:00Z', data: {…}},   
     {time: '2022-01-25T06:00:00Z', data: {…}},    
     {time: '2022-01-25T07:00:00Z', data: {…}},   
     {time: '2022-01-25T14:00:00Z', data: {…}},        
     {time: '2022-01-25T15:00:00Z', data: {…}},    
     {time: '2022-01-26T13:00:00Z', data: {…}},
     {time: '2022-01-26T14:00:00Z', data: {…}},
     {time: '2022-01-26T15:00:00Z', data: {…}},
     {time: '2022-01-27T13:00:00Z', data: {…}},
     {time: '2022-01-27T14:00:00Z', data: {…}},
     {time: '2022-01-27T15:00:00Z', data: {…}},
     {time: '2022-01-28T14:00:00Z', data: {…}},     
     {time: '2022-01-28T15:00:00Z', data: {…}},    
     {time: '2022-01-28T16:00:00Z', data: {…}},    
     {time: '2022-01-29T18:00:00Z', data: {…}},    
     {time: '2022-01-29T19:00:00Z', data: {…}},    
     {time: '2022-01-30T08:00:00Z', data: {…}},    
     {time: '2022-01-30T09:00:00Z', data: {…}},    
     {time: '2022-01-30T10:00:00Z', data: {…}},    
     {time: '2022-01-30T11:00:00Z', data: {…}},    
    ]

That is the sample code.

Upvotes: 1

Views: 846

Answers (2)

RobG
RobG

Reputation: 147503

An algorithm is:

  1. Sort the data by the value of the time property
  2. Find the index of the first day on the same date as the start date
  3. If an element is found, push that element into an array
  4. Increment the search date by 1 day

A lexical sort is used to sort on time and to find the records to return as it's an ISO 8601 string. Conversion to Date objects will work too but that seems unnecessary.

To select each date, dStart is set to the start of the UTC day and dEnd is set to the end of the UTC day. If no date is found in that range, none is added to the array. This prevents the case of a multi day gap in the data producing multiple entries of the same object (i.e. the first one after the gap) in the selected array.

If this should be based on local dates, then use setHours instead of setUTCHours.

/* Given data as an array of objects, return
 * first on date plus first on next n days
 * Dates are UTC, not local
 */
function getFirstNDays(data, n = 1, date = new Date()) {

  // Make sure n is a positive integer
  if (n % 1 || n < 0) return;

  data.sort((a, b) => a.time.localeCompare(b.time)); 

  let dStart = new Date(date);
  dStart.setUTCHours(0,0,0,0);

  let dEnd = new Date(dStart);
  dEnd.setUTCHours(23,59,59,999);
  let selected = [];
  
  while (n--) {
    let index = data.findIndex(obj => obj.time >= dStart.toISOString() && obj.time <= dEnd.toISOString());

    // If record found, add to selected array
    if (index != -1) {
      selected.push(data[index]);
    }

    dStart.setUTCDate(dStart.getUTCDate() + 1);
    dEnd.setUTCDate(dEnd.getUTCDate() + 1);
  }

  // Return selected values
  return selected;
}

let daysdata = [
  {time: '2022-01-20T11:00:00Z', data: {}},   
  {time: '2022-01-23T11:00:00Z', data: {}},   
  {time: '2022-01-23T12:00:00Z', data: {}},   
  {time: '2022-01-24T11:00:00Z', data: {}},   
  {time: '2022-01-24T12:00:00Z', data: {}},   
  {time: '2022-01-24T17:00:00Z', data: {}},   
  {time: '2022-01-24T23:00:00Z', data: {}},   
  {time: '2022-01-25T00:00:00Z', data: {}},   
  {time: '2022-01-25T04:00:00Z', data: {}},   
  {time: '2022-01-25T05:00:00Z', data: {}},   
  {time: '2022-01-25T06:00:00Z', data: {}},    
  {time: '2022-01-25T07:00:00Z', data: {}},   
  {time: '2022-01-25T14:00:00Z', data: {}},        
  {time: '2022-01-25T15:00:00Z', data: {}},    
  {time: '2022-01-26T13:00:00Z', data: {}},
  {time: '2022-01-26T14:00:00Z', data: {}},
  {time: '2022-01-26T15:00:00Z', data: {}},
  {time: '2022-01-27T13:00:00Z', data: {}},
  {time: '2022-01-27T14:00:00Z', data: {}},
  {time: '2022-01-27T15:00:00Z', data: {}},
  {time: '2022-01-28T14:00:00Z', data: {}},     
  {time: '2022-01-28T15:00:00Z', data: {}},    
  {time: '2022-01-28T16:00:00Z', data: {}},    
  {time: '2022-01-29T18:00:00Z', data: {}},    
  {time: '2022-01-29T19:00:00Z', data: {}},    
  {time: '2022-01-30T08:00:00Z', data: {}},    
  {time: '2022-01-30T09:00:00Z', data: {}},    
  {time: '2022-01-30T10:00:00Z', data: {}},    
  {time: '2022-01-30T11:00:00Z', data: {}},    
];

console.log(getFirstNDays(daysdata, 7, new Date(Date.UTC(2022,0,23))));

Updated to suit updated requirements.

Upvotes: 1

hossein vatankhah
hossein vatankhah

Reputation: 214

just sort by Array.sort and pick the first n elements of an array by Array.slice

 

daysdata = [{time: '2022-01-23T11:00:00Z', data: {}},   
     {time: '2022-01-23T12:00:00Z', data: {}},   
     {time: '2022-01-24T11:00:00Z', data: {}},   
     {time: '2022-01-24T12:00:00Z', data: {}},   
     {time: '2022-01-24T17:00:00Z', data: {}},   
     {time: '2022-01-24T23:00:00Z', data: {}},   
     {time: '2022-01-25T00:00:00Z', data: {}},   
     {time: '2022-01-25T04:00:00Z', data: {}},   
     {time: '2022-01-25T05:00:00Z', data: {}},   
     {time: '2022-01-25T06:00:00Z', data: {}},    
     {time: '2022-01-25T07:00:00Z', data: {}},   
     {time: '2022-01-25T14:00:00Z', data: {}},        
     {time: '2022-01-25T15:00:00Z', data: {}},    
     {time: '2022-01-26T13:00:00Z', data: {}},
     {time: '2022-01-26T14:00:00Z', data: {}},
     {time: '2022-01-26T15:00:00Z', data: {}},
     {time: '2022-01-27T13:00:00Z', data: {}},
     {time: '2022-01-27T14:00:00Z', data: {}},
     {time: '2022-01-27T15:00:00Z', data: {}},
     {time: '2022-01-28T14:00:00Z', data: {}},     
     {time: '2022-01-28T15:00:00Z', data: {}},    
     {time: '2022-01-28T16:00:00Z', data: {}},    
     {time: '2022-01-29T18:00:00Z', data: {}},    
     {time: '2022-01-29T19:00:00Z', data: {}},    
     {time: '2022-01-30T08:00:00Z', data: {}},    
     {time: '2022-01-30T09:00:00Z', data: {}},    
     {time: '2022-01-30T10:00:00Z', data: {}},    
     {time: '2022-01-30T11:00:00Z', data: {}},    
    ];

   sortData = daysdata.sort((a,b) => (a.time < b.time) ? 1 : ((b.time < a.time) ? -1 : 0));

   console.log(sortData.slice(0,7));

Upvotes: 1

Related Questions