21

I want to filter the below json data by start date and end date, it should return the data between start date and end date, I tried to achieve using below code but I'm doing wrong something to filter. I'm new to front end technologies like Javascript and jquery, it would be appreciated if Someone can correct me what I'm doing wrong here:

<html>
    <head>
        <title>Test</title>

    </head>

    <body>

        <script type="text/javascript">
            var product_data = [
                {
                    "productId": "12",
                    "productName": "ProductA",
                    "productPrice": "1562",
                    "ProductDateCreated": "2015-07-24T12:58:17.430Z",
                    "TotalProduct": 294
                },
                {
                    "productId": "13",
                    "productName": "ProductB",
                    "productPrice": "8545",
                    "TotalProduct": 294,
                    "ProductHits": {
                        "2015-08-01T00:00:00Z"
                    }
                },
                {
                    "productId": "14",
                    "productName": "ProductC",
                    "productPrice": "8654",
                    "TotalProduct": 78,
                    "ProductHits": {
                        "2015-08-10T00:00:00Z"
                    }
                },
                {
                    "productId": "15",
                    "productName": "ProductD",
                    "productPrice": "87456",
                    "TotalProduct": 878,
                    "ProductHits": {
                        "2015-05-12T00:00:00Z"
                    }
                }
            ];

            var startDate = "2015-08-04";
            var endDate = "2015-08-12";

            var resultProductData = product_data.filter(
                    function (a)
                    {
                        return (a.ProductHits) > startDate && (a.ProductHits) < endDate;
                    });
            console.log(resultProductData);
        </script>

    </body>
</html>
7
  • 1
    you compare strings. you have to compare dates. Solution: convert the strings to Date objects and compare them. EDIT: ProductHits is no string. it's an object. you have to convert all keys of this object and compare them one by one. Commented Aug 13, 2015 at 0:45
  • How to convert key as object? Commented Aug 13, 2015 at 0:50
  • first: tell me pls why there are spaces in your date strings after the colons? Commented Aug 13, 2015 at 0:56
  • second: tell me pls the rule for ProductHits. there are multiple entries (dates). have they all match the range or only one of them? Commented Aug 13, 2015 at 1:00
  • aaand (last one ;)). are you sure it shell be ProductHits and not ProductDateCreated ? In my opnion that would make more sense... Commented Aug 13, 2015 at 1:04

6 Answers 6

20
        var startDate = new Date("2015-08-04");
        var endDate = new Date("2015-08-12");

        var resultProductData = product_data.filter(function (a) {
            var hitDates = a.ProductHits || {};
            // extract all date strings
            hitDates = Object.keys(hitDates);
            // convert strings to Date objcts
            hitDates = hitDates.map(function(date) { return new Date(date); });
            // filter this dates by startDate and endDate
            var hitDateMatches = hitDates.filter(function(date) { return date >= startDate && date <= endDate });
            // if there is more than 0 results keep it. if 0 then filter it away
            return hitDateMatches.length>0;
        });
        console.log(resultProductData);

fiddle: http://jsfiddle.net/4nz1ahuw/


UPDATE as Ates Goral suggests in the comments the solution above can be optimized by using Array.protype.some:

        var startDate = new Date("2015-08-04");
        var endDate = new Date("2015-08-12");

        var resultProductData = product_data.filter(function (a) {
            var hitDates = a.ProductHits || {};
            // extract all date strings
            hitDates = Object.keys(hitDates);
            // improvement: use some. this is an improment because .map()
            // and .filter() are walking through all elements.
            // .some() stops this process if one item is found that returns true in the callback function and returns true for the whole expression
            hitDateMatchExists = hitDates.some(function(dateStr) {
                var date = new Date(dateStr);
                return date >= startDate && date <= endDate
            });
            return hitDateMatchExists;
        });
        console.log(resultProductData);

thank you for your good advice :)

Sign up to request clarification or add additional context in comments.

6 Comments

You can also use Array.prototype.some as an optimization: return Object.keys(a.ProductHits || {}).some(function (dateStr) { var date = new Date(dateStr); return date >= startDate && date <= endDate; }); (Terminates the iteration the moment there's a match.)
@AtesGoral good advice. Feel free to edit it into the post as an update block if you want. thank you :)
My pleasure. I didn't want to spoil the clarity of your original answer :)
@AtesGoral added your solution to the answer. I hope it is also clearly documented ;)
@jquerybeginner that depends on your timezone. see the -0700 at the end of the date? 17:00:00 o'clock + 7 hours are midnight. If you want to vonvert the date to GMT +0 you can use Date.prototype.getTimezoneOffset() and Date.prototype.valueOf(). but think about it: dows it matter? all dates are changed the same way and you compare them with greater and lower operators. so... it shouldn't matter ;)
|
18

I could not get the above solutions to work. I found a slight modification to the approved answer that worked for me here . The code snippet below got the job done.

var startDate = new Date("2015-08-04");
var endDate = new Date("2015-08-12");

var resultProductData = product_data.filter(a => {
  var date = new Date(a.ProductHits);
  return (date >= startDate && date <= endDate);
});
console.log(resultProductData)

Comments

3

For you, the dates values need to be encapsulated as such eg. new Date(your date value)

Another approach is given using the following example as a guide:

https://jsfiddle.net/ladiv7/tb66ya67/

/*Dummy Data, Courtesy of: https://www.generatedata.com/*/
var dataDates = [{
    "date": "Nov 28, 2017",
    "name": "Samuel A. Kidd",
    "email": "[email protected]",
    "address": "944-343 Nec Avenue"
  },
  {
    "date": "May 20, 2015",
    "name": "Jenna R. Alston",
    "email": "[email protected]",
    "address": "5316 Mollis Av."
  },
  {
    "date": "Mar 11, 2018",
    "name": "Magee K. Mcfarland",
    "email": "[email protected]",
    "address": "Ap #605-1298 Id Rd."
  },
  {
    "date": "Dec 9, 2016",
    "name": "Claudia V. Campbell",
    "email": "[email protected]",
    "address": "Ap #935-7909 Lectus Rd."
  },
  {
    "date": "Aug 4, 2015",
    "name": "Steven V. Reynolds",
    "email": "[email protected]",
    "address": "Ap #501-8119 Vel, Rd."
  },
  {
    "date": "Mar 25, 2019",
    "name": "Amy O. Bean",
    "email": "[email protected]",
    "address": "1855 Euismod Ave"
  },
  {
    "date": "Jan 12, 2019",
    "name": "Quintessa H. Clay",
    "email": "[email protected]",
    "address": "P.O. Box 127, 812 Lobortis Rd."
  },
  {
    "date": "Feb 7, 2015",
    "name": "Marvin P. Golden",
    "email": "[email protected]",
    "address": "P.O. Box 936, 8921 Augue Av."
  },
  {
    "date": "Aug 4, 2015",
    "name": "Shay Z. Clayton",
    "email": "[email protected]",
    "address": "5862 Pede St."
  },
  {
    "date": "Feb 12, 2015",
    "name": "Jin G. Jimenez",
    "email": "[email protected]",
    "address": "4310 Malesuada Av."
  },
  {
    "date": "Feb 10, 2017",
    "name": "Dawn R. Blackwell",
    "email": "[email protected]",
    "address": "5585 Metus. St."
  },
  {
    "date": "Apr 28, 2015",
    "name": "Audra A. Gates",
    "email": "[email protected]",
    "address": "448-332 Iaculis Ave"
  },
  {
    "date": "May 6, 2018",
    "name": "Gloria K. Dodson",
    "email": "[email protected]",
    "address": "564-3879 Vel, St."
  },
  {
    "date": "Jan 1, 2015",
    "name": "Inga I. Vinson",
    "email": "[email protected]",
    "address": "320-4632 Lacus. Road"
  },
  {
    "date": "Jul 21, 2015",
    "name": "Berk M. Owen",
    "email": "[email protected]",
    "address": "727 Bibendum Ave"
  },
  {
    "date": "Feb 27, 2016",
    "name": "Jessica C. Thompson",
    "email": "[email protected]",
    "address": "P.O. Box 903, 2394 A, St."
  }
];



$(document).ready(function() {

  $('.datepicker').datepicker(); //Activates the datepicker Materialize CSS element

  preview_json(dataDates, $("#view_rawData")); //show the original data on the screen
  $("#count_RawData").html("(" + dataDates.length + ")");

  $("#filter-button").click(function(e) {

    console.log("Hello world");

    //Gets the form data in a unified manner
    var getFormData = {
      dates: {
        start: $("#date_from").val(),
        end: $("#date_to").val()
      }
    };

    //Function to filter the result
    var filteredData = dateFilterer(dataDates, getFormData.dates.start, getFormData.dates.end);
    preview_json(filteredData.finalValues, $("#view_filteredData")); //show the final result on the screen
    $("#count_FilteredData").html("(" + filteredData.finalValues.length + ")");

  });


});


//Filter function to ensure that the final result set is within a particular range
function dateFilterer(sourceValues, startDate, endDate) {

  /*Curtosy of the tutorial found here: https://www.w3schools.com/jsref/jsref_filter.asp*/
  function filterFunction_dates(sourceValue) {

    //Aim: To test if the tested date is valid within a particular range
    var rangeAcceptance = {
      minValid: new Date(sourceValue.date) >= new Date(startDate),
      maxValid: new Date(sourceValue.date) <= new Date(endDate)
    };

    var acceptanceResult; //boolean to determine if the relevant range specified is valid

    if (startDate != "" && endDate != "") {

      acceptanceResult = (rangeAcceptance.minValid && rangeAcceptance.maxValid);

    } else if (startDate != "") {

      acceptanceResult = rangeAcceptance.minValid;

    } else if (endDate != "") {

      acceptanceResult = rangeAcceptance.maxValid;

    } else {

      acceptanceResult = (1 == 1); //show all results if no specific range has been selected

    }

    return (acceptanceResult);

  }

  /*console.log({

    originalValues: sourceValues,
    finalValues: sourceValues.filter(filterFunction_dates),
    "time of filter": new Date()

  });*/

  //Return the data for display
  return ({

    originalValues: sourceValues,
    finalValues: sourceValues.filter(filterFunction_dates)

  });

}



//Aim: To make the dates into something that the Range filter function can work with
function normalize_date(fieldValue) {

  var monthPossibilities = {
    longStructure: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
    shortStructure: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
  }; //To store what the month values could possibly be for returning their relevant index number

  var datePartitions = fieldValue.split(", ");
  var year = datePartitions[1];
  var month = datePartitions[0].substring(0, 3); //first three characters of section 1

  if (monthPossibilities.longStructure.indexOf(month) > -1) {

    month = (monthPossibilities.longStructure.indexOf(month) + 1).toString(); //Increments by one to give the actual month number

  } else if (monthPossibilities.shortStructure.indexOf(month) > -1) {

    month = (monthPossibilities.shortStructure.indexOf(month) + 1).toString();

  } else {

    month = "";

  }

  //Aim: Add that customary zero to prepend the date value
  if ((month.length < 2) && (month.length > 0)) {

    month = "0" + month;

  }

  var day = datePartitions[0].slice(-2); //last two characters of section 1    
  var finalResult = year + "-" + month + "-" + day;

  return (finalResult);

}




//Aim: Display json in a nicely formatted way
function preview_json(data, target) {

  /*Curtosy of fellow fiddler: http://jsfiddle.net/unLSJ/*/
  var library = {};

  library.json = {
    replacer: function(match, pIndent, pKey, pVal, pEnd) {
      var key = '<span class=json-key>';
      var val = '<span class=json-value>';
      var str = '<span class=json-string>';
      var r = pIndent || '';
      if (pKey)
        r = r + key + pKey.replace(/[": ]/g, '') + '</span>: ';
      if (pVal)
        r = r + (pVal[0] == '"' ? str : val) + pVal + '</span>';
      return r + (pEnd || '');
    },
    prettyPrint: function(obj) {
      var jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg;
      return JSON.stringify(obj, null, 3)
        .replace(/&/g, '&amp;').replace(/\\"/g, '&quot;')
        .replace(/</g, '&lt;').replace(/>/g, '&gt;')
        .replace(jsonLine, library.json.replacer);
    }
  };

  //Show json in desired target
  target.html(library.json.prettyPrint(data));

}
#count_RawData {
  color: #89cbfa;
}

#view_rawData,
#view_filteredData {
  min-height: 50px;
  max-height: 700px;
  overflow-y: scroll;
  width: 100%;
  box-shadow: 0 0 5px #cfcfcf;
  border-radius: 5px;
  border: none;
}

#count_FilteredData {
  color: #498e88;
}

#filter-button {
  width: 100%;
}

#filter_section {
  width: 100%;
  margin-left: auto;
  margin-right: auto;
  padding: 20px;
  /* background-color: #f1f1f1; */
  border: 1px solid #cfcfcf;
}


/*Curtosy of the fellow fiddler's code: http://jsfiddle.net/unLSJ/*/

pre {
  background-color: ghostwhite;
  border: 1px solid silver;
  padding: 10px 20px;
  margin: 20px;
}

.json-key {
  color: brown;
}

.json-value {
  color: navy;
}

.json-string {
  color: olive;
}


/*Update the scrollbar*/

::-webkit-scrollbar {
  width: 7px;
}

::-webkit-scrollbar-track {
  -webkit-box-shadow: inset 0 0 10px rgb(255, 255, 255);
  border-radius: 10px;
}

::-webkit-scrollbar-thumb {
  border-radius: 10px;
  -webkit-box-shadow: inset 0 0 6px rgba(132, 144, 154);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0" />
  <title>JSON - Date Range Filter Concept</title>

  <!-- CSS  -->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

  <link href="https://materializecss.com/templates/starter-template/css/style.css" rel="stylesheet" />
  <link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css" rel="stylesheet" />

  <link href="css/style.css" type="text/css" rel="stylesheet" media="screen,projection" />

</head>

<body>

  <nav class="light-blue lighten-1" role="navigation">
    <div class="nav-wrapper container"><a id="logo-container" href="#" class="brand-logo">JSON Date Range Filter</a>
      <ul class="right hide-on-med-and-down">
        <li><a href="#">Home</a></li>
      </ul>

      <ul id="nav-mobile" class="sidenav">
        <li><a href="#">Home</a></li>
      </ul>

      <a href="#" data-target="nav-mobile" class="sidenav-trigger">
        <i class="material-icons">menu</i>
      </a>
    </div>
  </nav>

  <div class="container">

    <div class="section">

      <!--   Raw Data Section   -->
      <div class="row">
        <div class="col s12">
          <div class="icon-block">
            <h4 class="center">Raw Data <small id="count_RawData">(0)</small></h4>
            <pre id="view_rawData" class="light">
              Your raw data will be previewed here
            </pre>
          </div>
        </div>
      </div>

      <!--Filter Form-->
      <div class="row center" id="filter_section">
        <div class="input-field col s6">
          <input id="date_from" type="text" placeholder="From" class="datepicker">
        </div>
        <div class="input-field col s6">
          <input id="date_to" type="text" placeholder="To" class="datepicker">
        </div>
        <button id="filter-button" class="btn-large waves-effect waves-light">Filtra</button>
      </div>

      <!--   Filtered Data Section   -->
      <div class="row">
        <div class="col s12">
          <div class="icon-block">
            <h4 class="center">Filtered Data <small id="count_FilteredData">(0)</small></h4>
            <pre id="view_filteredData" class="light">
              Your final data will be previewed here
            </pre>
          </div>
        </div>
      </div>

    </div>

    <br><br>
  </div>

</body>

</html>


<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script src="https://materializecss.com/templates/starter-template/js/init.js"></script>

3 Comments

Looks like you forgot to include the example ^
Did you want the iframe, or did you just want to link to the Fiddle? Iframes don't work here (thankfully).
My bad.. thanks for the intel. Just updated the post for more clarity. Hope it helps someone out there.
0

This is how I do filter between two dates. I am filtering data from yesterday to last7Days.

public itemFilter()
{ 
  var now = new Date();
  let yesterday=new Date(new Date().getTime() - (1 * 24 * 60 * 60 * 1000));
  let last7Days=new Date(new Date().getTime() - (7 * 24 * 60 * 60 * 1000));
  var data=obj.filter(p => new Date(p.LastSeenDate) <= yesterday && new Date(p.LastSeenDate) >= last3Days);     
}

Here LastSeenDate is date of our product.

Comments

0

Hi you can use moment

moment('2010-10-20').isBetween('2010-10-19', '2010-10-25');

Here is the link to the doc : https://momentjs.com/docs/#/query/is-dst-shifted/

1 Comment

Not sure, why this was downvoted but It was exactly what I was looking for. Straight forward and to the point.
0

Refactoring joshua k's approach to make it simple

const data = product_data.filter(data => {
  if(!data.ProductHits) {return};
  const [strDate] = Object.keys(data.ProductHits);           
  const date = new Date(strDate);
  return date > new Date('2015-05-01') && date < new Date('2015-08-10')
 });
 console.log(data);
 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.