diff --git a/lib/cartodb/backends/dataview.js b/lib/cartodb/backends/dataview.js index dc43f864..ca451d38 100644 --- a/lib/cartodb/backends/dataview.js +++ b/lib/cartodb/backends/dataview.js @@ -20,7 +20,7 @@ function DataviewBackend(analysisBackend) { this.analysisBackend = analysisBackend; } -var DATE_AGGREGATIONS = ['minute', 'hour', 'day', 'week', 'month', 'year']; +var DATE_AGGREGATIONS = ['minute', 'hour', 'day', 'week', 'month', 'quarter', 'year']; module.exports = DataviewBackend; diff --git a/lib/cartodb/models/dataview/histogram.js b/lib/cartodb/models/dataview/histogram.js index 1328383d..be4c7193 100644 --- a/lib/cartodb/models/dataview/histogram.js +++ b/lib/cartodb/models/dataview/histogram.js @@ -136,7 +136,11 @@ var dateBinsQueryTpl = dot.template([ ' FROM (', ' SELECT', ' ARRAY(', + ' {{?it._aggregation==="quarter"}}', + ' SELECT GENERATE_SERIES(start_date, end_date, \'3 month\'::interval)', + ' {{??}}', ' SELECT GENERATE_SERIES(start_date, end_date, \'1 {{=it._aggregation}}\'::interval)', + ' {{?}}', ' ) AS bins_array', ' FROM basics', ' ) _cdb_bins_array', diff --git a/test/acceptance/dataviews/histogram.js b/test/acceptance/dataviews/histogram.js index 5e4de9b9..0efb56d6 100644 --- a/test/acceptance/dataviews/histogram.js +++ b/test/acceptance/dataviews/histogram.js @@ -307,4 +307,46 @@ describe('histogram-dataview for date column type', function() { done(); }); }); + + it('should aggregate histogram using "quarter" aggregation', function (done) { + var TIMEZONE_UTC_IN_SECONDS = 0 * 3600; // UTC + var TIMEZONE_UTC_IN_MINUTES = 0 * 60; // UTC + var params = { + timezone: TIMEZONE_UTC_IN_SECONDS, + aggregation: 'quarter' + }; + + this.testClient = new TestClient(mapConfig, 1234); + this.testClient.getDataview('date_histogram', params, function(err, dataview) { + assert.ok(!err, err); + assert.equal(dataview.type, 'histogram'); + assert.ok(dataview.bin_width > 0, 'Unexpected bin width: ' + dataview.bin_width); + assert.equal(dataview.bins.length, 6); + + var initialTimestamp = '2007-01-01T00:00:00Z'; // UTC midnight + var binsStartInMilliseconds = dataview.bins_start * 1000; + var binsStartFormatted = moment.utc(binsStartInMilliseconds) + .utcOffset(TIMEZONE_UTC_IN_MINUTES) + .format(); + assert.equal(binsStartFormatted, initialTimestamp); + + dataview.bins.forEach(function(bin, index) { + var binTimestampExpected = moment.utc(initialTimestamp) + .utcOffset(TIMEZONE_UTC_IN_MINUTES) + .add(index * 3, 'month') + .format(); + var binsTimestampInMilliseconds = bin.timestamp * 1000; + var binTimestampFormatted = moment.utc(binsTimestampInMilliseconds) + .utcOffset(TIMEZONE_UTC_IN_MINUTES) + .format(); + + assert.equal(binTimestampFormatted, binTimestampExpected); + assert.ok(bin.timestamp <= bin.min, 'bin timestamp < bin min: ' + JSON.stringify(bin)); + assert.ok(bin.min <= bin.max, 'bin min < bin max: ' + JSON.stringify(bin)); + }); + + done(); + }); + }); + });