1

I have a json document that looks like this:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "time": 1438342780,
        "title": "Iran's foreign minister calls for world's nuclear weapons states to disarm",
        "author": "Julian Borger",
        "web_id": "world/2015/jul/31/iran-nuclear-weapons-states-disarm-israel"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -77.26526,
          38.90122
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "time": 1438300867,
        "title": "Big bangs over the white cliffs of Dover as unique 1915 artillery gun is fired again",
        "author": "Maev Kennedy",
        "web_id": "world/2015/jul/31/big-bangs-over-white-cliffs-dover-unique-1915-artillery-gun-fired-again"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          1.3,
          51.13333
        ]
      }
    }
  ]
}

I would like to fetch the 'feature' array inside json and return the number of features for a given day. For example, for the data above I would expect something like:

{
  "date": 7/31/2015,
  "number": 2
}

Currently I have something that looks like this:

d3.json('path/to/json', function(json) {
    data = json;
});

Fairly new to js and d3 so a bit stumped. Let me know if you need any more details. Thanks in advance!

Morrisda
  • 1,380
  • 1
  • 11
  • 25
sammy88888888
  • 458
  • 1
  • 5
  • 18

4 Answers4

2

This will work for you, it returns an array of object. each object is the object you asked.

var a = yourJSONObject, var map = {}, output = [];
for (var i = 0; i < a.features.length; i++) {
 var ref = new Date(a.features[i].properties.time*1000).toDateString();
 if (map[ref] == undefined) {
  map[ref] = output.push({
    date: ref,
    number: 1
  }) - 1;
 } else 
    output[map[ref]].number++
}

console.log(output) //[ { date: 'Sat Jan 17 1970', number: 2 } ]
Morrisda
  • 1,380
  • 1
  • 11
  • 25
  • This is almost exactly what I'm looking for except that the date parse is returning all dates in 1970 when they are in 2015 according to http://www.epochconverter.com. Any thoughts? – sammy88888888 Feb 25 '16 at 16:35
  • Take the date parsing from my example. – Adrian Lynch Feb 25 '16 at 16:44
  • 1
    Yes, i didn't realize your time reference was an unix timestamp. Just multiply for 1000. See my edit above @sammy88888888 – Morrisda Feb 25 '16 at 16:44
1

The critical piece here is that your time values are in Epoch time, which means you'll have to convert them to preset dates using this technique.

Then you can traverse the features array, and track the count for each date.

var features = yourJSONObject.features;
var featuresByDate = {};

for (var i = 0, len = features.length; i < len; i++) {
    // find the current feature's date
    var epochTime = features[0].properties.time;
    var date = new Date(0);
    date.setUTCSeconds(epochTime);

    // find the date in 7/31/2015 format
    var dateStr = (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();

    // count the date for the first time if it has not been counted yet
    if ( ! featuresByDate.hasOwnProperty(dateStr) ) {
         featuresByDate[dateStr] = 1;
    }
    // otherwise, increment its counter
    else {
         featuresByDate[dateStr]++;
    }
}
Community
  • 1
  • 1
Stiliyan
  • 1,154
  • 1
  • 9
  • 15
0

Two functions - one to get the correct date based on the epoch time, the other to iterate through the features building a temporary object, then iterating through the object to give you an array of date/number objects.

function getDate(time) {
  var d = new Date(0);
  d.setUTCSeconds(time);
  return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/');
}

function getData(data) {
  var obj = data.features.reduce(function(p, c) {
    var date = getDate(c.properties.time);
    p[date] = (p[date] + 1) || 1;
    return p;
  }, {});
  return Object.keys(obj).map(function (el) {
    return { date: el, number: obj[el] };
  });
}

getData(data);

OUTPUT

[
  {
    "date": "7/31/2015",
    "number": 2
  }
]

DEMO

Community
  • 1
  • 1
Andy
  • 61,948
  • 13
  • 68
  • 95
-1

I don't know D3, but you can do this with straight JS:

var json = {
    "features": [{
        "type": "Feature",
        "properties": {
            "time": 1438342780,
            "title": "Iran's foreign minister calls for world's nuclear weapons states to disarm"
        }
    }, {
        "type": "Feature",
        "properties": {
            "time": 1438300867,
            "title": "Big bangs over the white cliffs of Dover as unique 1915 artillery gun is fired again"
        }
    }, {
        "type": "Feature same date",
        "properties": {
            "time": 1448300867,
            "title": "Big bangs over the white cliffs of Dover as unique 1915 artillery gun is fired again"
        }
    }]
}

var counts = {}

function secondsToDate(seconds) {
    var date = new Date(1970,0,1);
    date.setSeconds(seconds);
    return date.toDateString();
}

json.features.reduce((counts, feature) => {
    var date = secondsToDate(feature.properties.time)
    if (counts[date]) {
        counts[date]++
    } else {
        counts[date] = 1
    }
    return counts
}, counts)

console.log(counts) // {'Fri Jul 31 2015': 2, 'Mon Nov 23 2015': 1}

The missing bit is parsing your timestamp into a date.

Now grouping on dates. Maybe now the downvoter can undo that!

I added an object with a replicated timestamp to highlight the count going up.

Adrian Lynch
  • 8,237
  • 2
  • 32
  • 40