Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions src/utils/dataFormatters/__test__/formatUptime.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,58 @@
import {getDowntimeFromDateFormatted, getUptimeFromDateFormatted} from '../dataFormatters';
import {EMPTY_DATA_PLACEHOLDER} from '../../constants';
import {UNBREAKABLE_GAP} from '../../utils';
import {
formatUptimeInSeconds,
getDowntimeFromDateFormatted,
getUptimeFromDateFormatted,
} from '../dataFormatters';

describe('getUptimeFromDateFormatted', () => {
it('should calculate and format uptime', () => {
expect(getUptimeFromDateFormatted(3_600_000, 7_200_000)).toBe('1:00:00');
});
it('should return 0 if dateFrom after dateTo', () => {
expect(getUptimeFromDateFormatted(3_600_000, 3_599_000)).toBe('0:00:00');
expect(getUptimeFromDateFormatted(3_600_000, 3_599_000)).toBe('0s');
});
});
describe('getDowntimeFromDateFormatted', () => {
it('should calculate and format downtime as -uptime', () => {
expect(getDowntimeFromDateFormatted(3_600_000, 7_200_000)).toBe('-1:00:00');
});
it('should not add sign if downtime is 0', () => {
expect(getDowntimeFromDateFormatted(3_600_000, 3_600_000)).toBe('0:00:00');
expect(getDowntimeFromDateFormatted(3_600_000, 3_600_000)).toBe('0s');
});
it('should return 0 if dateFrom after dateTo', () => {
expect(getDowntimeFromDateFormatted(3_600_000, 3_599_000)).toBe('0:00:00');
expect(getDowntimeFromDateFormatted(3_600_000, 3_599_000)).toBe('0s');
});
});
describe('formatUptimeInSeconds', () => {
const M = 60;
const H = 60 * M;
const D = 24 * H;

it('should return days if value is more than 24h', () => {
expect(formatUptimeInSeconds(D)).toBe('1d' + UNBREAKABLE_GAP + '00:00:00');
expect(formatUptimeInSeconds(D + H + M + 12)).toBe('1d' + UNBREAKABLE_GAP + '01:01:12');
expect(formatUptimeInSeconds(12 * D + 12 * H + 12 * M + 12)).toBe(
'12d' + UNBREAKABLE_GAP + '12:12:12',
);
expect(formatUptimeInSeconds(1234 * D + 12 * H + 12 * M + 12)).toBe(
'1234d' + UNBREAKABLE_GAP + '12:12:12',
);
});
it('should return hours if value is less than 24h', () => {
expect(formatUptimeInSeconds(H + M + 12)).toBe('1:01:12');
expect(formatUptimeInSeconds(12 * H + 12 * M + 12)).toBe('12:12:12');
});
it('should return minutes if value is less than hour', () => {
expect(formatUptimeInSeconds(M + 12)).toBe('1:12');
expect(formatUptimeInSeconds(12 * M + 2)).toBe('12:02');
});
it('should return second if value is less than hour', () => {
expect(formatUptimeInSeconds(12)).toBe('12s');
expect(formatUptimeInSeconds(2)).toBe('2s');
});
it('should return empty placeholder on NaN', () => {
expect(formatUptimeInSeconds(Number.NaN)).toBe(EMPTY_DATA_PLACEHOLDER);
});
});
38 changes: 26 additions & 12 deletions src/utils/dataFormatters/dataFormatters.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {dateTimeParse} from '@gravity-ui/date-utils';
import {dateTimeParse, duration} from '@gravity-ui/date-utils';

import type {TVDiskID, TVSlotId} from '../../types/api/vdisk';
import {
formatBytes as formatBytesCustom,
getSizeWithSignificantDigits,
} from '../bytesParsers/formatBytes';
import type {BytesSizes} from '../bytesParsers/formatBytes';
import {DAY_IN_SECONDS, HOUR_IN_SECONDS} from '../constants';
import {EMPTY_DATA_PLACEHOLDER, HOUR_IN_SECONDS} from '../constants';
import {configuredNumeral} from '../numeral';
import {isNumeric} from '../utils';
import {UNBREAKABLE_GAP, isNumeric} from '../utils';

import {formatValues} from './common';
import {formatNumberWithDigits, getNumberWithSignificantDigits} from './formatNumber';
Expand Down Expand Up @@ -40,19 +40,33 @@ export const stringifyVdiskId = (id?: TVDiskID | TVSlotId) => {
return id ? Object.values(id).join('-') : '';
};

export const formatUptimeInSeconds = (seconds: number) => {
const days = Math.floor(seconds / DAY_IN_SECONDS);
const remain = seconds % DAY_IN_SECONDS;
/**
* It works well only with positive values,
* if you want to get negative formatted uptime, use some wrapper like getDowntimeFromDateFormatted
*/
export function formatUptimeInSeconds(seconds: number) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets handle somehow negative values. As for me this function should work properly with all values. And we should use it for negative and positive uptime.

if (!isNumeric(seconds)) {
return EMPTY_DATA_PLACEHOLDER;
}

const uptime = [days && `${days}d`, configuredNumeral(remain).format('00:00:00')]
.filter(Boolean)
.join(' ');
const d = duration(seconds, 's').rescale();

return uptime;
};
if (d.days() > 0) {
return d.format(`d[${i18n('d')}${UNBREAKABLE_GAP}]hh:mm:ss`);
}

if (d.hours() > 0) {
return d.format('h:mm:ss');
}
if (d.minutes() > 0) {
return d.format('m:ss');
}

return d.format(`s[${i18n('s')}]`);
}

export const formatMsToUptime = (ms?: number) => {
return ms && formatUptimeInSeconds(ms / 1000);
return formatUptimeInSeconds(Number(ms) / 1000);
};

export function getUptimeFromDateFormatted(dateFrom?: number | string, dateTo?: number | string) {
Expand Down
5 changes: 4 additions & 1 deletion src/utils/dataFormatters/i18n/en.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"format-cpu.cores": ["core", "cores", "cores", "cores"]
"format-cpu.cores": ["core", "cores", "cores", "cores"],

"d": "d",
"s": "s"
}
3 changes: 1 addition & 2 deletions src/utils/dataFormatters/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {registerKeysets} from '../../i18n';

import en from './en.json';
import ru from './ru.json';

const COMPONENT = 'ydb-format-cpu';

export default registerKeysets(COMPONENT, {ru, en});
export default registerKeysets(COMPONENT, {en});
3 changes: 0 additions & 3 deletions src/utils/dataFormatters/i18n/ru.json

This file was deleted.

2 changes: 1 addition & 1 deletion src/utils/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export function prepareNodeSystemState(
const DC = systemState.Location?.DataCenter || systemState.DataCenter;
const TenantName = systemState?.Tenants?.[0];

let Uptime: string;
let Uptime: PreparedNodeSystemState['Uptime'];

if (systemState.DisconnectTime) {
Uptime = getDowntimeFromDateFormatted(systemState.DisconnectTime);
Expand Down
8 changes: 7 additions & 1 deletion tests/suites/nodes/nodes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,13 @@ test.describe('Test Nodes Paginated Table', async () => {
const uptimeValues = await paginatedTable.getColumnValues('Uptime');

for (const uptime of uptimeValues) {
expect(uptime).toMatch(/^(\d+d\s)?(\d+):(\d{2}):(\d{2})$/); // Format: DDd? HH:MM:SS
// \d+d\xa0\d{2}:\d{2}:\d{2} - DDd HH:MM:SS, 1d 00:20:30
// \d{1,2}:\d{2}:\d{2}$ - HH:MM:SS, 1:02:02 or 12:02:02
// \d{1,2}:\d{2}$ - MM:SS, 1:02 or 12:02
// \d{1,2}s$ - SSs, 1s or 12s
expect(uptime).toMatch(
/^(\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)$/,
);
}
});

Expand Down
Loading