0

I would like to know how to get data between date range in javascript

I have object array obj and variables sdate and edate,

how to get array object if the cdate falls between the range sdate and edate

function getdate(){
     var finals=[];
     var result = obj.orders.filter(e=>{
     if(e.cdate < sdate && e.cdate > edate){
       finals.push(e); 
     }
  })

}

var obj={
  orders:[
      {id:1, mode: "xyz", orderid: 123, cdate: "2017-2-13 07:33:30"},
      {id:2, mode: "abc", orderid: 456, cdate: "2018-4-20 06:10:30"},
      {id:3, mode: "xyz", orderid: 768, cdate: "2020-8-10 08:00:00"}
  ]
}

var sdate="11-5-2020"
var edate="20-2-2021"


Expected Output

[
  {id:3, mode: "xyz", orderid: 768, cdate: "2020-8-10 08:00:00"}
]

ved
  • 167
  • 9
  • 1
    `if(e.cdate < sdate && e.cdate > edate)` you switched the conditions there. It should probably be `if(e.cdate > sdate && e.cdate < edate)`. Futhermore, your comparisions will fail if you have dates like `2017-8-13` and `2017-10-13` because currently you comparing strings, and there `2017-10-...` will be less than `2017-8...` so you have to convert your strings to datevalues first, or use a proper ISO format ie `2017-08-10...` – derpirscher Sep 17 '21 at 11:48
  • Please check the solutions and try to accept the correct answer and close this thread. – Nitheesh Sep 18 '21 at 15:06

3 Answers3

2

You have several issues

Wrong test for between: date >= sdate && date <= edate is what you need

If you cannot change the sdate, edate and the object dates, you can still format and still do string manipulation which is faster and safer than date manipulation due to timezones and daylight savings times

let obj={
  orders:[
      {id:1, mode: "xyz", orderid: 123, cdate: "2017-2-13 07:33:30"},
      {id:2, mode: "abc", orderid: 456, cdate: "2018-4-20 06:10:30"},
      {id:3, mode: "xyz", orderid: 768, cdate: "2020-8-10 08:00:00"}
  ]
}

const getyyyymmdd = str => {
  const parts = str.split(" ")[0].split("-")
  return parts[0].length === 2 ? `${parts[2]}-${parts[1].padStart(2, '0')}-${parts[0].padStart(2, '0')}` : `${parts[0].padStart(2, '0')}-${parts[1].padStart(2, '0')}-${parts[2]}`
}

function getdate(sdate,edate){
  sdate = getyyyymmdd(sdate)
  edate = getyyyymmdd(edate)
  return obj.orders.filter(({cdate}) => {
    cdate = getyyyymmdd(cdate); 
    return cdate >= sdate && cdate <= edate
  })
}


console.log(getdate("11-5-2020","20-2-2021"))

Alternatively if you can change either of the dates, you can add leading 0s to the object and swap the order of the start and end date

let obj={
  orders:[
      {id:1, mode: "xyz", orderid: 123, cdate: "2017-02-13 07:33:30"},
      {id:2, mode: "abc", orderid: 456, cdate: "2018-04-20 06:10:30"},
      {id:3, mode: "xyz", orderid: 768, cdate: "2020-08-10 08:00:00"}
  ]
}


function getdate(sdate,edate){
  return obj.orders.filter(item => {
    return item.cdate.split(" ")[0] >= sdate && item.cdate.split(" ")[0] <= edate
  })
}


console.log(getdate("2020-05-11","2021-02-20"))
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • `var sdate="11-5-2020"; var edate="20-2-2021"` The start date and enddates mentioned in question are these. They are not in standard date format. You may have to use this input and convet them to standard format. – Nitheesh Sep 17 '21 at 12:11
  • As I mentioned, *I* changed the order. Of course if that is not possible, I would need to manipulate the strings – mplungjan Sep 17 '21 at 12:15
  • @Nitheesh see update – mplungjan Sep 17 '21 at 12:23
2

In your attemot you are comparing your sdate and edate with cdate node from the onjects in array. This will berform only string comparison, since both of them are strings. To perform Date comparison, you have to convert both of them into Date objects. Your cdate is a standard date object, so new Date() will retun the date object for the string.

But your sdate and edate are not valid date strings. So I have splitted them and created new date object using that. Comparing the date objects will provide you the expected result.

Also I have set hours of endDate to 23, 59, 59, 999. This is to ensure that if a date in array comes with the same date as end date, that should be filtered out. Because that is the maximum value for end date for the particular day.

Also you dont need to push finals.push(e) inside the filter function. Instead you could simply return the status of that comparison inside your filter. This will generate a new array. This will be your expected result.

Your logic for calculating the value inbetween two dates is wrong. i have corrected that aswell.

var sdate = "11-5-2020";
var edate = "20-2-2021";

var obj = {
  orders: [
    { id: 1, mode: "xyz", orderid: 123, cdate: "2017-2-13 07:33:30" },
    { id: 2, mode: "abc", orderid: 456, cdate: "2018-4-20 06:10:30" },
    { id: 3, mode: "xyz", orderid: 768, cdate: "2020-8-10 08:00:00" }
  ]
}

function getdate() {
  var finals = [];
  const [sDay, sMonth, sYear] = sdate.split('-');
  const [eDay, eMonth, eYear] = edate.split('-');
  const startDate = new Date(sYear, +sMonth - 1, sDay);
  const endDate = new Date(eYear, +eMonth - 1, eDay, 23, 59, 59, 999);
  var result = obj.orders.filter(e => (new Date(e.cdate) >= startDate && new Date(e.cdate) <= endDate));
  return result;
}

console.log(getdate());

Please Note You can perform string comparison with dates if they are in standard ISO format. If your want to make use of that, you need to make the start and end date to iso format and perfrom comparison. So the filter statement will be

var result = obj.orders.filter(e => e.cdate >= startDate.toISOString() && e.cdate <= endDate.toISOString());
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
Nitheesh
  • 19,238
  • 3
  • 22
  • 49
  • No need for date comparison if the strings are ascii comparable – mplungjan Sep 17 '21 at 11:56
  • Yeah, since they are not standard format, I nned to convert them somehow. Or I could update my filter logic as `var result = obj.orders.filter(e => e.cdate > startDate.toISOString() && e.cdate < endDate.toISOString());` – Nitheesh Sep 17 '21 at 12:04
  • @3limin4t0r That is a good observation. I have updated my answer with that feedback – Nitheesh Sep 17 '21 at 14:12
0

You can get the desired result by first converting the string into Date object by passing the string in right format using helper function createDateObj.

Then using filter and get the result as

return arr.filter((o) => {
    const date = new Date(o.cdate);
    return date - start > 0 && end - start > 0;
  })

var sdate = "11-5-2020";
var edate = "20-2-2021";

function createDateObj(str) {
  const [a, b, c] = str.split("-");
  return `${b}-${a}-${c}`;
}

function getdate(arr) {
  const start = new Date(createDateObj(sdate));
  const end = new Date(createDateObj(edate));

  return arr.filter((o) => {
    const date = new Date(o.cdate);
    return date - start > 0 && end - start > 0;
  });
}

var obj = {
  orders: [
    { id: 1, mode: "xyz", orderid: 123, cdate: "2017-2-13 07:33:30" },
    { id: 2, mode: "abc", orderid: 456, cdate: "2018-4-20 06:10:30" },
    { id: 3, mode: "xyz", orderid: 768, cdate: "2020-8-10 08:00:00" },
  ],
};

console.log(getdate(obj.orders));
DecPK
  • 24,537
  • 6
  • 26
  • 42
  • 1
    No need for date comparison if the strings are ascii comparable – mplungjan Sep 17 '21 at 11:56
  • @mplungjan Didn't know that. Thank you – DecPK Sep 17 '21 at 11:59
  • 1
    @mplungjan They are not in standard ISO 8601 format so you can't because. `"2000-7-1" < "2000-10-1" //=> false` because `"7" > "1"`. Normally numbers are zero-prefixed which makes this work. `"2000-07-01" < "2000-10-01" //=> true` – 3limin4t0r Sep 17 '21 at 12:42
  • IF they are. - I should have said "so we can make them ascii comparable instead" [See my answer](https://stackoverflow.com/a/69222989/295783). I add the missing 0s in both examples - either on the server or in the script – mplungjan Sep 17 '21 at 12:59