]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Time diff service 28968/head
authorStephan Müller <smueller@suse.com>
Wed, 27 Mar 2019 12:27:51 +0000 (13:27 +0100)
committerStephan Müller <smueller@suse.com>
Thu, 25 Jul 2019 09:22:21 +0000 (11:22 +0200)
The time diff service can easily calculate the difference between two
dates and print it out in a human readable duration format. It also can
calculate a end or start date based on a date and a duration string.

Fixes: https://tracker.ceph.com/issues/36722
Signed-off-by: Stephan Müller <smueller@suse.com>
(cherry picked from commit 3fb21de8fdebcabe7f0871266194dc53cfef4986)

src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.ts [new file with mode: 0644]

diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.spec.ts
new file mode 100644 (file)
index 0000000..59b52ae
--- /dev/null
@@ -0,0 +1,66 @@
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { TimeDiffService } from './time-diff.service';
+
+describe('TimeDiffService', () => {
+  let service: TimeDiffService;
+  const baseTime = new Date('2022-02-22T00:00:00');
+
+  configureTestBed({
+    providers: [TimeDiffService]
+  });
+
+  beforeEach(() => {
+    service = TestBed.get(TimeDiffService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+
+  it('calculates a new date that happens after the given date', () => {
+    expect(service.calculateDate(new Date('2022-02-28T04:05:00'), '2h')).toEqual(
+      new Date('2022-02-28T06:05:00')
+    );
+    expect(service.calculateDate(baseTime, '15m')).toEqual(new Date('2022-02-22T00:15'));
+    expect(service.calculateDate(baseTime, '5d 23h')).toEqual(new Date('2022-02-27T23:00'));
+  });
+
+  it('calculates a new date that happens before the given date', () => {
+    expect(service.calculateDate(new Date('2022-02-22T02:00:00'), '2h', true)).toEqual(baseTime);
+  });
+
+  it('calculates the difference of two dates', () => {
+    expect(
+      service.calculateDuration(new Date('2022-02-22T00:45:00'), new Date('2022-02-22T02:00:00'))
+    ).toBe('1h 15m');
+    expect(service.calculateDuration(baseTime, new Date('2022-02-28T04:05:00'))).toBe('6d 4h 5m');
+  });
+
+  describe('testing duration calculation in detail', () => {
+    const minutes = 60 * 1000;
+    const hours = 60 * minutes;
+    const days = 24 * hours;
+
+    it('should allow different writings', () => {
+      const expectDurationToBeMs = (duration, ms) =>
+        expect(service['getDurationMs'](duration)).toBe(ms);
+      expectDurationToBeMs('2h', 2 * hours);
+      expectDurationToBeMs('4 Days', 4 * days);
+      expectDurationToBeMs('3 minutes', 3 * minutes);
+      expectDurationToBeMs('4 Days 2h 3 minutes', 4 * days + 2 * hours + 3 * minutes);
+      expectDurationToBeMs('5d3h120m', 5 * days + 5 * hours);
+    });
+
+    it('should create duration string from ms', () => {
+      const expectMsToBeDuration = (ms, duration) =>
+        expect(service['getDuration'](ms)).toBe(duration);
+      expectMsToBeDuration(2 * hours, '2h');
+      expectMsToBeDuration(4 * days, '4d');
+      expectMsToBeDuration(3 * minutes, '3m');
+      expectMsToBeDuration(4 * days + 2 * hours + 3 * minutes, '4d 2h 3m');
+      expectMsToBeDuration(service['getDurationMs']('5d3h120m'), '5d 5h');
+    });
+  });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.ts
new file mode 100644 (file)
index 0000000..051d104
--- /dev/null
@@ -0,0 +1,51 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class TimeDiffService {
+  constructor() {}
+
+  calculateDuration(startDate: Date, endDate: Date): string {
+    const startTime = +startDate;
+    const endTime = +endDate;
+    const duration = this.getDuration(Math.abs(startTime - endTime));
+    if (startTime > endTime) {
+      return '-' + duration;
+    }
+    return duration;
+  }
+
+  private getDuration(ms: number): string {
+    const date = new Date(ms);
+    const h = date.getUTCHours();
+    const m = date.getUTCMinutes();
+    const d = Math.floor(ms / (24 * 3600 * 1000));
+
+    const format = (n, s) => (n ? n + s : n);
+    return [format(d, 'd'), format(h, 'h'), format(m, 'm')].filter((x) => x).join(' ');
+  }
+
+  calculateDate(date: Date, duration: string, reverse?: boolean): Date {
+    const time = +date;
+    if (_.isNaN(time)) {
+      return;
+    }
+    const diff = this.getDurationMs(duration) * (reverse ? -1 : 1);
+    return new Date(time + diff);
+  }
+
+  private getDurationMs(duration: string): number {
+    const d = this.getNumbersFromString(duration, 'd');
+    const h = this.getNumbersFromString(duration, 'h');
+    const m = this.getNumbersFromString(duration, 'm');
+    return ((d * 24 + h) * 60 + m) * 60000;
+  }
+
+  private getNumbersFromString(duration, prefix): number {
+    const match = duration.match(new RegExp(`[0-9 ]+${prefix}`, 'i'));
+    return match ? parseInt(match, 10) : 0;
+  }
+}