Skip to content

Commit d40aea0

Browse files
feat: change uptime format (#1748)
1 parent b12599e commit d40aea0

File tree

7 files changed

+95
-28
lines changed

7 files changed

+95
-28
lines changed
Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,67 @@
1-
import {getDowntimeFromDateFormatted, getUptimeFromDateFormatted} from '../dataFormatters';
1+
import {EMPTY_DATA_PLACEHOLDER} from '../../constants';
2+
import {UNBREAKABLE_GAP} from '../../utils';
3+
import {
4+
formatUptimeInSeconds,
5+
getDowntimeFromDateFormatted,
6+
getUptimeFromDateFormatted,
7+
} from '../dataFormatters';
28

39
describe('getUptimeFromDateFormatted', () => {
410
it('should calculate and format uptime', () => {
511
expect(getUptimeFromDateFormatted(3_600_000, 7_200_000)).toBe('1:00:00');
612
});
713
it('should return 0 if dateFrom after dateTo', () => {
8-
expect(getUptimeFromDateFormatted(3_600_000, 3_599_000)).toBe('0:00:00');
14+
expect(getUptimeFromDateFormatted(3_600_000, 3_599_000)).toBe('0s');
915
});
1016
});
1117
describe('getDowntimeFromDateFormatted', () => {
1218
it('should calculate and format downtime as -uptime', () => {
1319
expect(getDowntimeFromDateFormatted(3_600_000, 7_200_000)).toBe('-1:00:00');
1420
});
1521
it('should not add sign if downtime is 0', () => {
16-
expect(getDowntimeFromDateFormatted(3_600_000, 3_600_000)).toBe('0:00:00');
22+
expect(getDowntimeFromDateFormatted(3_600_000, 3_600_000)).toBe('0s');
1723
});
1824
it('should return 0 if dateFrom after dateTo', () => {
19-
expect(getDowntimeFromDateFormatted(3_600_000, 3_599_000)).toBe('0:00:00');
25+
expect(getDowntimeFromDateFormatted(3_600_000, 3_599_000)).toBe('0s');
26+
});
27+
});
28+
describe('formatUptimeInSeconds', () => {
29+
const M = 60;
30+
const H = 60 * M;
31+
const D = 24 * H;
32+
33+
it('should return days if value is more than 24h', () => {
34+
expect(formatUptimeInSeconds(D)).toBe('1d' + UNBREAKABLE_GAP + '00:00:00');
35+
expect(formatUptimeInSeconds(D + H + M + 12)).toBe('1d' + UNBREAKABLE_GAP + '01:01:12');
36+
expect(formatUptimeInSeconds(12 * D + 12 * H + 12 * M + 12)).toBe(
37+
'12d' + UNBREAKABLE_GAP + '12:12:12',
38+
);
39+
expect(formatUptimeInSeconds(1234 * D + 12 * H + 12 * M + 12)).toBe(
40+
'1234d' + UNBREAKABLE_GAP + '12:12:12',
41+
);
42+
});
43+
it('should return hours if value is less than 24h', () => {
44+
expect(formatUptimeInSeconds(H + M + 12)).toBe('1:01:12');
45+
expect(formatUptimeInSeconds(12 * H + 12 * M + 12)).toBe('12:12:12');
46+
});
47+
it('should return minutes if value is less than hour', () => {
48+
expect(formatUptimeInSeconds(M + 12)).toBe('1:12');
49+
expect(formatUptimeInSeconds(12 * M + 2)).toBe('12:02');
50+
});
51+
it('should return second if value is less than hour', () => {
52+
expect(formatUptimeInSeconds(12)).toBe('12s');
53+
expect(formatUptimeInSeconds(2)).toBe('2s');
54+
});
55+
it('should correctly process negative values', () => {
56+
expect(formatUptimeInSeconds(-0)).toBe('0s');
57+
expect(formatUptimeInSeconds(-12)).toBe('-12s');
58+
expect(formatUptimeInSeconds(-1 * (12 * M + 2))).toBe('-12:02');
59+
expect(formatUptimeInSeconds(-1 * (12 * H + 12 * M + 12))).toBe('-12:12:12');
60+
expect(formatUptimeInSeconds(-1 * (12 * D + 12 * H + 12 * M + 12))).toBe(
61+
'-12d' + UNBREAKABLE_GAP + '12:12:12',
62+
);
63+
});
64+
it('should return empty placeholder on NaN', () => {
65+
expect(formatUptimeInSeconds(Number.NaN)).toBe(EMPTY_DATA_PLACEHOLDER);
2066
});
2167
});

src/utils/dataFormatters/dataFormatters.ts

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import {dateTimeParse} from '@gravity-ui/date-utils';
1+
import {dateTimeParse, duration} from '@gravity-ui/date-utils';
22

33
import type {TVDiskID, TVSlotId} from '../../types/api/vdisk';
44
import {
55
formatBytes as formatBytesCustom,
66
getSizeWithSignificantDigits,
77
} from '../bytesParsers/formatBytes';
88
import type {BytesSizes} from '../bytesParsers/formatBytes';
9-
import {DAY_IN_SECONDS, HOUR_IN_SECONDS} from '../constants';
9+
import {EMPTY_DATA_PLACEHOLDER, HOUR_IN_SECONDS} from '../constants';
1010
import {configuredNumeral} from '../numeral';
11-
import {isNumeric} from '../utils';
11+
import {UNBREAKABLE_GAP, isNumeric} from '../utils';
1212

1313
import {formatValues} from './common';
1414
import {formatNumberWithDigits, getNumberWithSignificantDigits} from './formatNumber';
@@ -40,19 +40,38 @@ export const stringifyVdiskId = (id?: TVDiskID | TVSlotId) => {
4040
return id ? Object.values(id).join('-') : '';
4141
};
4242

43-
export const formatUptimeInSeconds = (seconds: number) => {
44-
const days = Math.floor(seconds / DAY_IN_SECONDS);
45-
const remain = seconds % DAY_IN_SECONDS;
43+
/**
44+
* It works well only with positive values,
45+
* if you want to get negative formatted uptime, use some wrapper like getDowntimeFromDateFormatted
46+
*/
47+
export function formatUptimeInSeconds(seconds: number) {
48+
if (!isNumeric(seconds)) {
49+
return EMPTY_DATA_PLACEHOLDER;
50+
}
4651

47-
const uptime = [days && `${days}d`, configuredNumeral(remain).format('00:00:00')]
48-
.filter(Boolean)
49-
.join(' ');
52+
// duration.format() doesn't work well with negative values
53+
// negative value will be displayed like -2d -12:-58:-21
54+
// so we process positive duration and only then add sign if any
55+
const sign = seconds < 0 ? '-' : '';
56+
const d = duration(Math.abs(seconds), 's').rescale();
5057

51-
return uptime;
52-
};
58+
let value: string;
59+
60+
if (d.days() > 0) {
61+
value = d.format(`d[${i18n('d')}${UNBREAKABLE_GAP}]hh:mm:ss`);
62+
} else if (d.hours() > 0) {
63+
value = d.format('h:mm:ss');
64+
} else if (d.minutes() > 0) {
65+
value = d.format('m:ss');
66+
} else {
67+
value = d.format(`s[${i18n('s')}]`);
68+
}
69+
70+
return sign + value;
71+
}
5372

5473
export const formatMsToUptime = (ms?: number) => {
55-
return ms && formatUptimeInSeconds(ms / 1000);
74+
return formatUptimeInSeconds(Number(ms) / 1000);
5675
};
5776

5877
export function getUptimeFromDateFormatted(dateFrom?: number | string, dateTo?: number | string) {
@@ -72,10 +91,7 @@ export function getDowntimeFromDateFormatted(dateFrom?: number | string, dateTo?
7291
// Prevent wrong negative uptime values
7392
diff = diff < 0 ? 0 : diff;
7493

75-
const formattedUptime = formatUptimeInSeconds(diff);
76-
77-
// Do not add sign to 0 values to prevent -0:00:00 uptime
78-
return diff === 0 ? formattedUptime : '-' + formattedUptime;
94+
return formatUptimeInSeconds(-diff);
7995
}
8096

8197
export function calcTimeDiffInSec(

src/utils/dataFormatters/i18n/en.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
{
2-
"format-cpu.cores": ["core", "cores", "cores", "cores"]
2+
"format-cpu.cores": ["core", "cores", "cores", "cores"],
3+
4+
"d": "d",
5+
"s": "s"
36
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import {registerKeysets} from '../../i18n';
22

33
import en from './en.json';
4-
import ru from './ru.json';
54

65
const COMPONENT = 'ydb-format-cpu';
76

8-
export default registerKeysets(COMPONENT, {ru, en});
7+
export default registerKeysets(COMPONENT, {en});

src/utils/dataFormatters/i18n/ru.json

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/utils/nodes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export function prepareNodeSystemState(
7474
const DC = systemState.Location?.DataCenter || systemState.DataCenter;
7575
const TenantName = systemState?.Tenants?.[0];
7676

77-
let Uptime: string;
77+
let Uptime: PreparedNodeSystemState['Uptime'];
7878

7979
if (systemState.DisconnectTime) {
8080
Uptime = getDowntimeFromDateFormatted(systemState.DisconnectTime);

tests/suites/nodes/nodes.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,13 @@ test.describe('Test Nodes Paginated Table', async () => {
9494
const uptimeValues = await paginatedTable.getColumnValues('Uptime');
9595

9696
for (const uptime of uptimeValues) {
97-
expect(uptime).toMatch(/^(\d+d\s)?(\d+):(\d{2}):(\d{2})$/); // Format: DDd? HH:MM:SS
97+
// \d+d\xa0\d{2}:\d{2}:\d{2} - DDd HH:MM:SS, 1d 00:20:30
98+
// \d{1,2}:\d{2}:\d{2}$ - HH:MM:SS, 1:02:02 or 12:02:02
99+
// \d{1,2}:\d{2}$ - MM:SS, 1:02 or 12:02
100+
// \d{1,2}s$ - SSs, 1s or 12s
101+
expect(uptime).toMatch(
102+
/^(\d+d\xa0\d{2}:\d{2}:\d{2}|\d{1,2}:\d{2}:\d{2}|\d{1,2}:\d{2}|\d{1,2}s)$/,
103+
);
98104
}
99105
});
100106

0 commit comments

Comments
 (0)