Просмотр исходного кода

Prettify duration value format (#6875)

* Prettify duration unit format

Format duration like "2 days, 19 hours, 48 minutes" and make Decimals useful e.g.
0 decimals: 2 days
2 decimals: 2 days, 19 hours, 48 minutes
3 decimals: 2 days, 19 hours, 48 minutes, 27 seconds

Previous code did some rounding that is now gone so numbers might be
different.

* Rewrite kbn.toDuration without moment.js

Because https://github.com/moment/moment/issues/3653

* Add tests for kbn.toDuration
Axel 9 лет назад
Родитель
Сommit
2adbe3e13e
2 измененных файлов с 113 добавлено и 9 удалено
  1. 42 9
      public/app/core/utils/kbn.js
  2. 71 0
      public/test/core/utils/kbn_specs.js

+ 42 - 9
public/app/core/utils/kbn.js

@@ -1,9 +1,8 @@
 define([
 define([
   'jquery',
   'jquery',
-  'lodash',
-  'moment'
+  'lodash'
 ],
 ],
-function($, _, moment) {
+function($, _) {
   'use strict';
   'use strict';
 
 
   var kbn = {};
   var kbn = {};
@@ -631,16 +630,50 @@ function($, _, moment) {
     }
     }
   };
   };
 
 
-  kbn.toDuration = function(size, timeScale) {
-    return moment.duration(size, timeScale);
+  kbn.toDuration = function(size, decimals, timeScale) {
+    if (size === null) { return ""; }
+    if (size === 0) { return "0 " + timeScale + "s"; }
+    if (size < 0) { return kbn.toDuration(-size, decimals, timeScale) + " ago"; }
+
+    var units = [
+      {short: "y",  long: "year"},
+      {short: "M",  long: "month"},
+      {short: "w",  long: "week"},
+      {short: "d",  long: "day"},
+      {short: "h",  long: "hour"},
+      {short: "m",  long: "minute"},
+      {short: "s",  long: "second"},
+      {short: "ms", long: "millisecond"}
+    ];
+    // convert $size to milliseconds
+    // intervals_in_seconds uses seconds (duh), convert them to milliseconds here to minimize floating point errors
+    size *= kbn.intervals_in_seconds[units.find(function(e) { return e.long === timeScale; }).short] * 1000;
+
+    var string = [];
+     // after first value >= 1 print only $decimals more
+    var decrementDecimals = false;
+    for (var i = 0; i < units.length && decimals >= 0; i++) {
+      var interval = kbn.intervals_in_seconds[units[i].short] * 1000;
+      var value = size / interval;
+      if (value >= 1 || decrementDecimals) {
+        decrementDecimals = true;
+        var floor = Math.floor(value);
+        var unit = units[i].long + (floor !== 1 ? "s" : "");
+        string.push(floor + " " + unit);
+        size = size % interval;
+        decimals--;
+      }
+    }
+
+    return string.join(", ");
   };
   };
 
 
-  kbn.valueFormats.dtdurationms = function(size) {
-    return kbn.toDuration(size, 'ms').humanize();
+  kbn.valueFormats.dtdurationms = function(size, decimals) {
+    return kbn.toDuration(size, decimals, 'millisecond');
   };
   };
 
 
-  kbn.valueFormats.dtdurations = function(size) {
-    return kbn.toDuration(size, 's').humanize();
+  kbn.valueFormats.dtdurations = function(size, decimals) {
+    return kbn.toDuration(size, decimals, 'second');
   };
   };
 
 
   ///// FORMAT MENU /////
   ///// FORMAT MENU /////

+ 71 - 0
public/test/core/utils/kbn_specs.js

@@ -214,4 +214,75 @@ define([
       expect(str).to.be('-0x41.8');
       expect(str).to.be('-0x41.8');
     });
     });
   });
   });
+
+  describe('duration', function() {
+    it('null', function() {
+      var str = kbn.toDuration(null, 0, "millisecond");
+      expect(str).to.be('');
+    });
+    it('0 milliseconds', function() {
+      var str = kbn.toDuration(0, 0, "millisecond");
+      expect(str).to.be('0 milliseconds');
+    });
+    it('1 millisecond', function() {
+      var str = kbn.toDuration(1, 0, "millisecond");
+      expect(str).to.be('1 millisecond');
+    });
+    it('-1 millisecond', function() {
+      var str = kbn.toDuration(-1, 0, "millisecond");
+      expect(str).to.be('1 millisecond ago');
+    });
+    it('seconds', function() {
+      var str = kbn.toDuration(1, 0, "second");
+      expect(str).to.be('1 second');
+    });
+    it('minutes', function() {
+      var str = kbn.toDuration(1, 0, "minute");
+      expect(str).to.be('1 minute');
+    });
+    it('hours', function() {
+      var str = kbn.toDuration(1, 0, "hour");
+      expect(str).to.be('1 hour');
+    });
+    it('days', function() {
+      var str = kbn.toDuration(1, 0, "day");
+      expect(str).to.be('1 day');
+    });
+    it('weeks', function() {
+      var str = kbn.toDuration(1, 0, "week");
+      expect(str).to.be('1 week');
+    });
+    it('months', function() {
+      var str = kbn.toDuration(1, 0, "month");
+      expect(str).to.be('1 month');
+    });
+    it('years', function() {
+      var str = kbn.toDuration(1, 0, "year");
+      expect(str).to.be('1 year');
+    });
+    it('decimal days', function() {
+      var str = kbn.toDuration(1.5, 2, "day");
+      expect(str).to.be('1 day, 12 hours, 0 minutes');
+    });
+    it('decimal months', function() {
+      var str = kbn.toDuration(1.5, 3, "month");
+      expect(str).to.be('1 month, 2 weeks, 1 day, 0 hours');
+    });
+    it('no decimals', function() {
+      var str = kbn.toDuration(38898367008, 0, "millisecond");
+      expect(str).to.be('1 year');
+    });
+    it('1 decimal', function() {
+      var str = kbn.toDuration(38898367008, 1, "millisecond");
+      expect(str).to.be('1 year, 2 months');
+    });
+    it('too many decimals', function() {
+      var str = kbn.toDuration(38898367008, 20, "millisecond");
+      expect(str).to.be('1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, 7 seconds, 8 milliseconds');
+    });
+    it('floating point error', function() {
+      var str = kbn.toDuration(36993906007, 8, "millisecond");
+      expect(str).to.be('1 year, 2 months, 0 weeks, 3 days, 4 hours, 5 minutes, 6 seconds, 7 milliseconds');
+    });
+  });
 });
 });