diff --git a/public/app/core/utils/datemath.ts b/public/app/core/utils/datemath.ts index 1e0179df827..1dac6d01126 100644 --- a/public/app/core/utils/datemath.ts +++ b/public/app/core/utils/datemath.ts @@ -7,103 +7,105 @@ var units = ['y', 'M', 'w', 'd', 'h', 'm', 's']; var unitsAsc = _.sortBy(units, function (unit) { return moment.duration(1, unit).valueOf(); }); + var unitsDesc = unitsAsc.reverse(); -export class DateMath { +function parse(text, roundUp?) { + if (!text) { return undefined; } + if (moment.isMoment(text)) { return text; } + if (_.isDate(text)) { return moment(text); } - static parse(text, roundUp?) { - if (!text) { return undefined; } - if (moment.isMoment(text)) { return text; } - if (_.isDate(text)) { return moment(text); } + var time; + var mathString = ''; + var index; + var parseString; - var time; - var mathString = ''; - var index; - var parseString; - - if (text.substring(0, 3) === 'now') { - time = moment(); - mathString = text.substring('now'.length); + 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 { - 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); + parseString = text.substring(0, index); + mathString = text.substring(index + 2); } - - if (!mathString.length) { - return time; - } - - return DateMath.parseDateMath(mathString, time, roundUp); + // We're going to just require ISO8601 timestamps, k? + time = moment(parseString); } - static parseDateMath(mathString, time, roundUp?) { - var dateTime = time; - var i = 0; - var len = mathString.length; - - while (i < len) { - var c = mathString.charAt(i++); - var type; - var num; - var 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 if (mathString.length === 2) { - num = mathString.charAt(i); - } else { - var numFrom = i; - while (!isNaN(mathString.charAt(i))) { - i++; - if (i > 10) { return undefined; } - } - 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(units, unit)) { - return undefined; - } else { - if (type === 0) { - if (roundUp) { - dateTime.endOf(unit); - } - else { - dateTime.startOf(unit); - } - } else if (type === 1) { - dateTime.add(num, unit); - } else if (type === 2) { - dateTime.subtract(num, unit); - } - } - } - return dateTime; + if (!mathString.length) { + return time; } + + return parseDateMath(mathString, time, roundUp); } +function parseDateMath(mathString, time, roundUp?) { + var dateTime = time; + var i = 0; + var len = mathString.length; + + while (i < len) { + var c = mathString.charAt(i++); + var type; + var num; + var 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 if (mathString.length === 2) { + num = mathString.charAt(i); + } else { + var numFrom = i; + while (!isNaN(mathString.charAt(i))) { + i++; + if (i > 10) { return undefined; } + } + 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(units, unit)) { + return undefined; + } else { + if (type === 0) { + if (roundUp) { + dateTime.endOf(unit); + } + else { + dateTime.startOf(unit); + } + } else if (type === 1) { + dateTime.add(num, unit); + } else if (type === 2) { + dateTime.subtract(num, unit); + } + } + } + return dateTime; +} + +export = { + parse: parse, + parseDateMath: parseDateMath +}; diff --git a/public/app/features/dashboard/timeSrv.js b/public/app/features/dashboard/timeSrv.js index 6bb9ccde223..9bf9512966f 100644 --- a/public/app/features/dashboard/timeSrv.js +++ b/public/app/features/dashboard/timeSrv.js @@ -3,8 +3,9 @@ define([ 'lodash', 'config', 'kbn', - 'moment' -], function (angular, _, config, kbn, moment) { + 'moment', + 'app/core/utils/datemath' +], function (angular, _, config, kbn, moment, dateMath) { 'use strict'; var module = angular.module('grafana.services'); @@ -131,8 +132,8 @@ define([ var _to = _t.to || new Date(); return { - from: kbn.parseDate(_from), - to: kbn.parseDate(_to) + from: dateMath.parse(_from, false), + to: dateMath.parse(_to, true) }; } }; diff --git a/public/app/features/dashboard/timepicker/timepicker.ts b/public/app/features/dashboard/timepicker/timepicker.ts index 5bfefa6427a..5cd0b6b7924 100644 --- a/public/app/features/dashboard/timepicker/timepicker.ts +++ b/public/app/features/dashboard/timepicker/timepicker.ts @@ -4,6 +4,7 @@ import angular = require('angular'); import _ = require('lodash'); import moment = require('moment'); import kbn = require('kbn'); +import dateMath = require('app/core/utils/datemath'); import {TimeRange} from './timerange'; export class TimePickerCtrl { @@ -59,11 +60,11 @@ export class TimePickerCtrl { getTimeObj(date): any { return { - date: new Date(date), - hour: this.pad(date.getHours(), 2), - minute: this.pad(date.getMinutes(), 2), - second: this.pad(date.getSeconds(), 2), - millisecond: this.pad(date.getMilliseconds(), 3) + date: date, + hour: this.pad(date.hours(), 2), + minute: this.pad(date.minutes(), 2), + second: this.pad(date.seconds(), 2), + millisecond: this.pad(date.milliseconds(), 3) }; }; @@ -154,7 +155,7 @@ export class TimePickerCtrl { this.timeSrv.setTime(range); - this.$scope.time = this.getScopeTimeObj(kbn.parseDate(range.from), new Date()); + this.$scope.time = this.getScopeTimeObj(dateMath.parse(range.from), moment()); } validate(time): any { diff --git a/public/app/panels/graph/graph.js b/public/app/panels/graph/graph.js index 0f6ae7baeeb..29fa913c9c4 100755 --- a/public/app/panels/graph/graph.js +++ b/public/app/panels/graph/graph.js @@ -285,8 +285,8 @@ function (angular, $, kbn, moment, _, GraphTooltip) { function addTimeAxis(options) { var ticks = elem.width() / 100; - var min = _.isUndefined(scope.range.from) ? null : scope.range.from.getTime(); - var max = _.isUndefined(scope.range.to) ? null : scope.range.to.getTime(); + var min = _.isUndefined(scope.range.from) ? null : scope.range.from.valueOf(); + var max = _.isUndefined(scope.range.to) ? null : scope.range.to.valueOf(); options.xaxis = { timezone: dashboard.timezone, diff --git a/public/app/plugins/datasource/graphite/datasource.js b/public/app/plugins/datasource/graphite/datasource.js index 400ec7abc77..4f3bdc92c13 100644 --- a/public/app/plugins/datasource/graphite/datasource.js +++ b/public/app/plugins/datasource/graphite/datasource.js @@ -3,14 +3,14 @@ define([ 'lodash', 'jquery', 'config', - 'kbn', + 'app/core/utils/datemath', 'moment', './directives', './queryCtrl', './funcEditor', './addGraphiteFunc', ], -function (angular, _, $, config, kbn, moment) { +function (angular, _, $, config, dateMath, moment) { 'use strict'; var module = angular.module('grafana.services'); @@ -29,8 +29,8 @@ function (angular, _, $, config, kbn, moment) { GraphiteDatasource.prototype.query = function(options) { try { var graphOptions = { - from: this.translateTime(options.range.from, 'round-down'), - until: this.translateTime(options.range.to, 'round-up'), + from: this.translateTime(options.range.from, false), + until: this.translateTime(options.range.to, true), targets: options.targets, format: options.format, cacheTimeout: options.cacheTimeout || this.cacheTimeout, @@ -135,7 +135,7 @@ function (angular, _, $, config, kbn, moment) { return this.doGraphiteRequest({ method: 'GET', - url: '/events/get_data?from=' + this.translateTime(options.range.from) + '&until=' + this.translateTime(options.range.to) + tags, + url: '/events/get_data?from=' + this.translateTime(options.range.from, false) + '&until=' + this.translateTime(options.range.to, true) + tags, }); } catch(err) { @@ -143,28 +143,30 @@ function (angular, _, $, config, kbn, moment) { } }; - GraphiteDatasource.prototype.translateTime = function(date, rounding) { + GraphiteDatasource.prototype.translateTime = function(date, roundUp) { if (_.isString(date)) { if (date === 'now') { return 'now'; } - else if (date.indexOf('now') >= 0) { + else if (date.indexOf('now-') >= 0) { date = date.substring(3); date = date.replace('m', 'min'); date = date.replace('M', 'mon'); return date; } - date = kbn.parseDate(date); + console.log('date: ' + date + ' round up: ' + roundUp); + date = dateMath.parse(date, roundUp); + console.log('date: ' + date + ' round up: ' + roundUp + ' ' + date.format('YYYY-MM-DD:HH:mm')); } date = moment.utc(date); - if (rounding === 'round-up') { + if (roundUp) { if (date.get('s')) { date.add(1, 'm'); } } - else if (rounding === 'round-down') { + else if (roundUp === false) { // graphite' s from filter is exclusive // here we step back one minute in order // to guarantee that we get all the data that diff --git a/public/test/specs/core/utils/datemath_specs.ts b/public/test/specs/core/utils/datemath_specs.ts index 64cebde4ed6..85e0f224807 100644 --- a/public/test/specs/core/utils/datemath_specs.ts +++ b/public/test/specs/core/utils/datemath_specs.ts @@ -1,10 +1,10 @@ -import {DateMath} from 'app/core/utils/datemath' import {describe, beforeEach, it, sinon, expect} from 'test/lib/common' +import dateMath = require('app/core/utils/datemath') import _ = require('lodash') import moment = require('moment') -describe.only("DateMath", () => { +describe("DateMath", () => { var spans = ['s', 'm', 'h', 'd', 'w', 'M', 'y']; var anchor = '2014-01-01T06:06:06.666Z'; var unix = moment(anchor).valueOf(); @@ -13,25 +13,25 @@ describe.only("DateMath", () => { describe('errors', () => { it('should return undefined if passed something falsy', () => { - expect(DateMath.parse(false)).to.be(undefined); + expect(dateMath.parse(false)).to.be(undefined); }); it('should return undefined if I pass an operator besides [+-/]', () => { - expect(DateMath.parse('now&1d')).to.be(undefined); + expect(dateMath.parse('now&1d')).to.be(undefined); }); it('should return undefined if I pass a unit besides' + spans.toString(), () => { - expect(DateMath.parse('now+5f')).to.be(undefined); + expect(dateMath.parse('now+5f')).to.be(undefined); }); it('should return undefined if rounding unit is not 1', () => { - expect(DateMath.parse('now/2y')).to.be(undefined); - expect(DateMath.parse('now/0.5y')).to.be(undefined); + expect(dateMath.parse('now/2y')).to.be(undefined); + expect(dateMath.parse('now/0.5y')).to.be(undefined); }); it('should not go into an infinite loop when missing a unit', () => { - expect(DateMath.parse('now-0')).to.be(undefined); - expect(DateMath.parse('now-00')).to.be(undefined); + expect(dateMath.parse('now-0')).to.be(undefined); + expect(dateMath.parse('now-00')).to.be(undefined); }); }); @@ -42,7 +42,7 @@ describe.only("DateMath", () => { expected.setSeconds(0); expected.setMilliseconds(0); - var startOfDay = DateMath.parse('now/d', false).valueOf() + var startOfDay = dateMath.parse('now/d', false).valueOf() expect(startOfDay).to.be(expected.getTime()); }); @@ -61,16 +61,16 @@ describe.only("DateMath", () => { var thenEx = anchor + '||-5' + span; it('should return 5' + span + ' ago', () => { - expect(DateMath.parse(nowEx).format(format)).to.eql(now.subtract(5, span).format(format)); + expect(dateMath.parse(nowEx).format(format)).to.eql(now.subtract(5, span).format(format)); }); it('should return 5' + span + ' before ' + anchor, () => { - expect(DateMath.parse(thenEx).format(format)).to.eql(anchored.subtract(5, span).format(format)); + expect(dateMath.parse(thenEx).format(format)).to.eql(anchored.subtract(5, span).format(format)); }); }); }); - describe('rounding', () => { + describe.only('rounding', () => { var now; var anchored; @@ -82,11 +82,11 @@ describe.only("DateMath", () => { _.each(spans, (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)); + 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)); + expect(dateMath.parse('now/' + span, true).format(format)).to.eql(now.endOf(span).format(format)); }); });