Skip to content

Commit

Permalink
Format durations
Browse files Browse the repository at this point in the history
  • Loading branch information
Assem-Hafez committed Jan 6, 2025
1 parent 8283643 commit 448b464
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
29 changes: 29 additions & 0 deletions src/utils/data-formatters/__tests__/format-duration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { type Duration } from '@/__generated__/proto-ts/google/protobuf/Duration';

import formatDuration from '../format-duration';

describe('formatDuration', () => {
it('should return "0s" for null duration', () => {
expect(formatDuration(null)).toBe('0s');
});

it('should format duration with only seconds', () => {
const duration: Duration = { seconds: '3600', nanos: 0 };
expect(formatDuration(duration)).toBe('1h');
});

it('should format duration with only nanoseconds', () => {
const duration: Duration = { seconds: '0', nanos: 500000000 };
expect(formatDuration(duration)).toBe('500ms');
});

it('should format duration with large values', () => {
const duration: Duration = { seconds: '31556952', nanos: 0 };
expect(formatDuration(duration)).toBe('1y, 5h, 49m, 12s');
});

it('should format duration with sub milliseconds', () => {
const duration: Duration = { seconds: '61', nanos: 123456789 };
expect(formatDuration(duration)).toBe('1m, 1s, 123.456789ms');
});
});
38 changes: 38 additions & 0 deletions src/utils/data-formatters/format-duration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { type Duration } from '@/__generated__/proto-ts/google/protobuf/Duration';
import dayjs from '@/utils/datetime/dayjs';

const formatDuration = (duration: Duration | null) => {
const defaultReturn = '0s';
if (!duration) {
return defaultReturn;
}
const secondsAsMillis = duration.seconds
? parseInt(duration.seconds) * 1000
: 0;
const nanosAsMillis = duration.nanos ? duration.nanos / 1000000 : 0;
const intMillis = Math.floor(nanosAsMillis);
const remainingNanosAsMillis = nanosAsMillis % 1;
const milliseconds = secondsAsMillis + intMillis;
const units = ['y', 'M', 'd', 'h', 'm', 's', 'ms'] as const;
const values: Partial<Record<(typeof units)[number], number>> = {};
let d = dayjs.duration(milliseconds);
units.forEach((unit) => {
const value = d.as(unit);
const intValue = Math.floor(value);
if (unit === 'ms') {
values[unit] = intValue + remainingNanosAsMillis;
} else {
values[unit] = intValue;
}
d = d.subtract(intValue, unit);
});

const result = units
.filter((unit) => values[unit])
.map((unit) => `${values[unit]}${unit}`)
.join(', ');

return result || defaultReturn;
};

export default formatDuration;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createElement } from 'react';

import formatDate from '@/utils/data-formatters/format-date';
import formatDuration from '@/utils/data-formatters/format-duration';
import WorkflowHistoryEventDetailsExecutionLink from '@/views/shared/workflow-history-event-details-wf-execution-link/workflow-history-event-details-wf-execution-link';

import WorkflowHistoryEventDetailsTaskListLink from '../../shared/workflow-history-event-details-task-list-link/workflow-history-event-details-task-list-link';
Expand Down Expand Up @@ -52,7 +53,9 @@ const workflowHistoryEventDetailsConfig = [
{
name: 'Duration timeout & backoff seconds',
pathRegex: '(TimeoutSeconds|BackoffSeconds)$',
valueComponent: ({ entryValue }) => `${entryValue}s`, // TODO @assem.hafez: format the value as duration
getLabel: ({ key }) => key.replace(/Seconds$/, ''), // remove seconds suffix from label as formatted duration can be minutes/hours etc.
valueComponent: ({ entryValue }) =>
formatDuration({ seconds: entryValue > 0 ? entryValue : 0, nanos: 0 }),
},
{
name: 'WorkflowExecution as link',
Expand Down

0 comments on commit 448b464

Please sign in to comment.