mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Date math parser and tests
This commit is contained in:
parent
5918df6a80
commit
00844d67bf
3 changed files with 236 additions and 2 deletions
91
src/kibana/utils/datemath.js
Normal file
91
src/kibana/utils/datemath.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
define(function (require) {
|
||||
var _ = require('lodash');
|
||||
var moment = require('moment');
|
||||
|
||||
/* This is a simplified version of elasticsearch's date parser */
|
||||
var parse = function (text, roundUp) {
|
||||
if (moment.isMoment(text)) return text;
|
||||
if (_.isDate(text)) return moment(text);
|
||||
|
||||
var time,
|
||||
mathString = '',
|
||||
index,
|
||||
parseString;
|
||||
if (text.substring(0, 3) === 'now') {
|
||||
time = moment();
|
||||
mathString = text.substring('now'.length);
|
||||
} else {
|
||||
index = text.indexOf('||');
|
||||
if (index === -1) {
|
||||
parseString = text;
|
||||
mathString = ''; // nothing else
|
||||
} else {
|
||||
parseString = text.substring(0, index);
|
||||
mathString = text.substring(index + 2);
|
||||
}
|
||||
// We're going to just require ISO8601 timestamps, k?
|
||||
time = moment(parseString);
|
||||
}
|
||||
|
||||
if (!mathString.length) {
|
||||
return time;
|
||||
}
|
||||
|
||||
return parseDateMath(mathString, time, roundUp);
|
||||
};
|
||||
|
||||
var parseDateMath = function (mathString, time, roundUp) {
|
||||
var dateTime = time,
|
||||
spans = ['s', 'm', 'h', 'd', 'w', 'M', 'y'];
|
||||
|
||||
for (var i = 0; i < mathString.length;) {
|
||||
var c = mathString.charAt(i++),
|
||||
type,
|
||||
num,
|
||||
unit;
|
||||
if (c === '/') {
|
||||
type = 0;
|
||||
} else if (c === '+') {
|
||||
type = 1;
|
||||
} else if (c === '-') {
|
||||
type = 2;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (isNaN(mathString.charAt(i))) {
|
||||
num = 1;
|
||||
} else {
|
||||
var numFrom = i;
|
||||
while (!isNaN(mathString.charAt(i))) {
|
||||
i++;
|
||||
}
|
||||
num = parseInt(mathString.substring(numFrom, i), 10);
|
||||
}
|
||||
if (type === 0) {
|
||||
// rounding is only allowed on whole, single, units (eg M or 1M, not 0.5M or 2M)
|
||||
if (num !== 1) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
unit = mathString.charAt(i++);
|
||||
|
||||
if (!_.contains(spans, unit)) {
|
||||
return undefined;
|
||||
} else {
|
||||
if (type === 0) {
|
||||
roundUp ? dateTime.endOf(unit) : dateTime.startOf(unit);
|
||||
} else if (type === 1) {
|
||||
dateTime.add(unit, num);
|
||||
} else if (type === 2) {
|
||||
dateTime.subtract(unit, num);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dateTime;
|
||||
};
|
||||
|
||||
return {
|
||||
parse: parse
|
||||
};
|
||||
});
|
|
@ -48,9 +48,8 @@
|
|||
function runTests() {
|
||||
require([
|
||||
'sinon/sinon',
|
||||
'specs/apps/dashboard/index',
|
||||
'specs/apps/dashboard/directives/panel',
|
||||
'specs/apps/dashboard/directives/grid',
|
||||
'specs/utils/datemath',
|
||||
'specs/services/state',
|
||||
'specs/courier/index'
|
||||
], function (sinon) {
|
||||
|
|
144
test/unit/specs/utils/datemath.js
Normal file
144
test/unit/specs/utils/datemath.js
Normal file
|
@ -0,0 +1,144 @@
|
|||
define(function (require) {
|
||||
var datemath = require('utils/datemath');
|
||||
var moment = require('moment');
|
||||
var _ = require('lodash');
|
||||
var sinon = require('sinon/sinon');
|
||||
|
||||
describe('datemath', function () {
|
||||
// Test each of these intervals when testing relative time
|
||||
var spans = ['s', 'm', 'h', 'd', 'w', 'M', 'y'],
|
||||
anchor = '2014-01-01T06:06:06.666Z',
|
||||
unix = moment(anchor).valueOf(),
|
||||
format = 'YYYY-MM-DDTHH:mm:ss.SSSZ',
|
||||
clock;
|
||||
|
||||
describe('errors', function () {
|
||||
it('should return undefined if I pass an operator besides [+-/]', function () {
|
||||
expect(datemath.parse('now&1d')).to.be(undefined);
|
||||
});
|
||||
|
||||
it('should return undefined if I pass a unit besides' + spans.toString(), function () {
|
||||
expect(datemath.parse('now+5f')).to.be(undefined);
|
||||
});
|
||||
|
||||
it('should return undefined if rounding unit is not 1', function () {
|
||||
expect(datemath.parse('now/2y')).to.be(undefined);
|
||||
expect(datemath.parse('now/0.5y')).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('objects and strings', function () {
|
||||
var mmnt, date, string, now;
|
||||
|
||||
beforeEach(function () {
|
||||
clock = sinon.useFakeTimers(unix);
|
||||
now = moment();
|
||||
mmnt = moment(anchor);
|
||||
date = mmnt.toDate();
|
||||
string = mmnt.format(format);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
it('should return the same moment if passed a moment', function () {
|
||||
expect(datemath.parse(mmnt)).to.eql(mmnt);
|
||||
});
|
||||
|
||||
it('should return a moment if passed a date', function () {
|
||||
expect(datemath.parse(date).format(format)).to.eql(mmnt.format(format));
|
||||
});
|
||||
|
||||
it('should return a moment if passed an ISO8601 string', function () {
|
||||
expect(datemath.parse(string).format(format)).to.eql(mmnt.format(format));
|
||||
});
|
||||
|
||||
it('should return the current time if passed now', function () {
|
||||
expect(datemath.parse('now').format(format)).to.eql(now.format(format));
|
||||
});
|
||||
});
|
||||
|
||||
describe('subtraction', function () {
|
||||
var now, anchored;
|
||||
|
||||
beforeEach(function () {
|
||||
clock = sinon.useFakeTimers(unix);
|
||||
now = moment();
|
||||
anchored = moment(anchor);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
_.each(spans, function (span) {
|
||||
var nowEx = 'now-5' + span;
|
||||
var thenEx = anchor + '||-5' + span;
|
||||
|
||||
it('should return 5' + span + ' ago', function () {
|
||||
expect(datemath.parse(nowEx).format(format)).to.eql(now.subtract(5, span).format(format));
|
||||
});
|
||||
|
||||
it('should return 5' + span + ' before ' + anchor, function () {
|
||||
expect(datemath.parse(thenEx).format(format)).to.eql(anchored.subtract(5, span).format(format));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('addition', function () {
|
||||
var now, anchored;
|
||||
|
||||
beforeEach(function () {
|
||||
clock = sinon.useFakeTimers(unix);
|
||||
now = moment();
|
||||
anchored = moment(anchor);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
_.each(spans, function (span) {
|
||||
var nowEx = 'now+5' + span;
|
||||
var thenEx = anchor + '||+5' + span;
|
||||
|
||||
it('should return 5' + span + ' from now', function () {
|
||||
expect(datemath.parse(nowEx).format()).to.eql(now.add(5, span).format());
|
||||
});
|
||||
|
||||
it('should return 5' + span + ' after ' + anchor, function () {
|
||||
expect(datemath.parse(thenEx).format()).to.eql(anchored.add(5, span).format());
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('rounding', function () {
|
||||
var now, anchored;
|
||||
|
||||
beforeEach(function () {
|
||||
clock = sinon.useFakeTimers(unix);
|
||||
now = moment();
|
||||
anchored = moment(anchor);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
_.each(spans, function (span) {
|
||||
it('should round now to the beginning of the ' + span, function () {
|
||||
expect(datemath.parse('now/' + span).format(format)).to.eql(now.startOf(span).format(format));
|
||||
});
|
||||
|
||||
it('should round now to the end of the ' + span, function () {
|
||||
expect(datemath.parse('now/' + span, true).format(format)).to.eql(now.endOf(span).format(format));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue