Javascript 如何在javascript中按日期范围过滤json数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31977724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to filter json data by date range in javascript
提问by jquery beginner
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:
我想通过开始日期和结束日期过滤下面的 json 数据,它应该返回开始日期和结束日期之间的数据,我试图使用下面的代码来实现,但我在过滤时做错了一些事情。我是 Javascript 和 jquery 等前端技术的新手,如果有人能纠正我在这里做错的事情,我将不胜感激:
<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>
回答by Joshua K
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/
小提琴:http: //jsfiddle.net/4nz1ahuw/
UPDATEas Ates Goral suggests in the comments the solution above can be optimized by using Array.protype.some:
更新正如 Ates Goral 在评论中所建议的,可以使用 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 :)
谢谢你的好建议:)
回答by vbricks
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/
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, '&').replace(/\"/g, '"')
.replace(/</g, '<').replace(/>/g, '>')
.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>