Skip to content

Commit

Permalink
Production package example: datemath (#16531)
Browse files Browse the repository at this point in the history
  • Loading branch information
kimjoar authored Feb 13, 2018
1 parent eb49a8c commit 1c3b404
Show file tree
Hide file tree
Showing 23 changed files with 2,201 additions and 69 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports = {
files: [
'.eslintrc.js',
'packages/kbn-build/**/*',
'packages/kbn-datemath/**/*.js',
'packages/kbn-plugin-generator/**/*',
],
plugins: ['prettier'],
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@
"url": "https://github.com/elastic/kibana.git"
},
"dependencies": {
"@elastic/datemath": "4.0.2",
"@elastic/eui": "0.0.19",
"@elastic/filesaver": "1.1.2",
"@elastic/numeral": "2.3.1",
"@elastic/ui-ace": "0.2.3",
"@kbn/babel-preset": "link:packages/kbn-babel-preset",
"@kbn/build": "link:packages/kbn-build",
"@kbn/datemath": "link:packages/kbn-datemath",
"@kbn/test-subj-selector": "link:packages/kbn-test-subj-selector",
"accept-language-parser": "1.2.0",
"angular": "1.6.5",
Expand Down
13 changes: 13 additions & 0 deletions packages/kbn-datemath/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"presets": [["env", {
"targets": {
"node": "current",
"browsers": [
"last 2 versions",
"> 5%",
"Safari 7",
]
}
}]],
"plugins": ["add-module-exports"]
}
20 changes: 20 additions & 0 deletions packages/kbn-datemath/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@kbn/datemath",
"version": "5.0.0",
"description": "elasticsearch datemath parser, used in kibana",
"license": "Apache-2.0",
"private": true,
"main": "target/index.js",
"scripts": {
"build": "babel src --out-dir target",
"kbn:bootstrap": "yarn build"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-preset-env": "^1.6.1"
},
"dependencies": {
"moment": "^2.13.0"
}
}
3 changes: 3 additions & 0 deletions packages/kbn-datemath/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# datemath

Datemath string parser used in Kibana
132 changes: 132 additions & 0 deletions packages/kbn-datemath/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import moment from 'moment';

const units = ['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms'];
const unitsDesc = units;
const unitsAsc = [...unitsDesc].reverse();

const isDate = d => Object.prototype.toString.call(d) === '[object Date]';

const isValidDate = d => isDate(d) && !isNaN(d.valueOf());

/*
* This is a simplified version of elasticsearch's date parser.
* If you pass in a momentjs instance as the third parameter the calculation
* will be done using this (and its locale settings) instead of the one bundled
* with this library.
*/
function parse(
text,
{ roundUp = false, momentInstance = moment, forceNow } = {}
) {
if (!text) return undefined;
if (momentInstance.isMoment(text)) return text;
if (isDate(text)) return momentInstance(text);
if (forceNow !== undefined && !isValidDate(forceNow)) {
throw new Error('forceNow must be a valid Date');
}

let time;
let mathString = '';
let index;
let parseString;

if (text.substring(0, 3) === 'now') {
time = momentInstance(forceNow);
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 = momentInstance(parseString);
}

if (!mathString.length) {
return time;
}

return parseDateMath(mathString, time, roundUp);
}

function parseDateMath(mathString, time, roundUp) {
const dateTime = time;
const len = mathString.length;
let i = 0;

while (i < len) {
const c = mathString.charAt(i++);
let type;
let num;
let unit;

if (c === '/') {
type = 0;
} else if (c === '+') {
type = 1;
} else if (c === '-') {
type = 2;
} else {
return;
}

if (isNaN(mathString.charAt(i))) {
num = 1;
} else if (mathString.length === 2) {
num = mathString.charAt(i);
} else {
const numFrom = i;
while (!isNaN(mathString.charAt(i))) {
i++;
if (i > 10) return;
}
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;
}
}

unit = mathString.charAt(i++);

// append additional characters in the unit
for (let j = i; j < len; j++) {
const unitChar = mathString.charAt(i);
if (/[a-z]/i.test(unitChar)) {
unit += unitChar;
i++;
} else {
break;
}
}

if (units.indexOf(unit) === -1) {
return;
} 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 default {
parse: parse,
units: Object.freeze(units),
unitsAsc: Object.freeze(unitsAsc),
unitsDesc: Object.freeze(unitsDesc),
};
Loading

0 comments on commit 1c3b404

Please sign in to comment.