mgr/dashboard: Time diff service

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>
This commit is contained in:
Stephan Müller 2019-03-27 13:27:51 +01:00
parent b20e9c8db8
commit 3fb21de8fd
2 changed files with 117 additions and 0 deletions

View File

@ -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');
});
});
});

View File

@ -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;
}
}