From d6255dae4e44437500e5a8d3c9cf7e613526f4d9 Mon Sep 17 00:00:00 2001 From: joseph-sentry Date: Wed, 11 Jun 2025 18:33:32 -0400 Subject: [PATCH 1/4] fix(ta): seconds to duration function --- src/shared/utils/dates.test.ts | 4 +++ src/shared/utils/dates.ts | 47 +++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/shared/utils/dates.test.ts b/src/shared/utils/dates.test.ts index 0ab5d9564e..c6f6dc98d6 100644 --- a/src/shared/utils/dates.test.ts +++ b/src/shared/utils/dates.test.ts @@ -34,4 +34,8 @@ describe('formatTimeFromSeconds', () => { it('returns the correct time format when totalSeconds is greater than 0', () => { expect(formatTimeFromSeconds(3661)).toBe('1h 1m 1s') }) + + it('returns the correct time format when totalSeconds is a float', () => { + expect(formatTimeFromSeconds(12901948.144373389)).toBe('149d 7h 52m 28s') + }) }) diff --git a/src/shared/utils/dates.ts b/src/shared/utils/dates.ts index 538588c782..fde1153b4b 100644 --- a/src/shared/utils/dates.ts +++ b/src/shared/utils/dates.ts @@ -1,9 +1,4 @@ -import { - formatDistanceToNow, - fromUnixTime, - intervalToDuration, - parseISO, -} from 'date-fns' +import { formatDistanceToNow, fromUnixTime, parseISO } from 'date-fns' export function formatTimeToNow(date?: string | number | null) { if (!date) return null @@ -16,19 +11,35 @@ export function formatTimeToNow(date?: string | number | null) { } export const formatTimeFromSeconds = (totalSeconds?: number | null) => { - if (totalSeconds === 0) return '0s' - if (!totalSeconds) return 'N/A' + if (totalSeconds === 0) { + return '0s' + } + if (totalSeconds == null || totalSeconds < 0) { + return 'N/A' + } - const duration = intervalToDuration({ start: 0, end: totalSeconds * 1000 }) + const days = Math.floor(totalSeconds / 86400) + const hours = Math.floor((totalSeconds % 86400) / 3600) + const minutes = Math.floor((totalSeconds % 3600) / 60) + const seconds = Math.floor(totalSeconds % 60) - const { days, hours, minutes, seconds } = duration + const timeParts = [] + if (days > 0) { + timeParts.push(`${days}d`) + } + if (hours > 0) { + timeParts.push(`${hours}h`) + } + if (minutes > 0) { + timeParts.push(`${minutes}m`) + } + if (seconds > 0) { + timeParts.push(`${seconds}s`) + } - return [ - days ? `${days}d` : '', - hours ? `${hours}h` : '', - minutes ? `${minutes}m` : '', - seconds ? `${seconds}s` : '', - ] - .filter(Boolean) - .join(' ') + if (timeParts.length === 0 && totalSeconds > 0) { + return '<1s' + } + + return timeParts.join(' ') } From cd396a0b459908e593c62b8e30e223bbbf5d59e8 Mon Sep 17 00:00:00 2001 From: joseph-sentry Date: Thu, 12 Jun 2025 11:20:36 -0400 Subject: [PATCH 2/4] address feedback --- src/shared/utils/dates.test.ts | 4 ++++ src/shared/utils/dates.ts | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/shared/utils/dates.test.ts b/src/shared/utils/dates.test.ts index c6f6dc98d6..d0a3972677 100644 --- a/src/shared/utils/dates.test.ts +++ b/src/shared/utils/dates.test.ts @@ -38,4 +38,8 @@ describe('formatTimeFromSeconds', () => { it('returns the correct time format when totalSeconds is a float', () => { expect(formatTimeFromSeconds(12901948.144373389)).toBe('149d 7h 52m 28s') }) + + it('returns the correct time format when totalSeconds is less than 1', () => { + expect(formatTimeFromSeconds(0.5)).toBe('<1s') + }) }) diff --git a/src/shared/utils/dates.ts b/src/shared/utils/dates.ts index fde1153b4b..2df8acedd2 100644 --- a/src/shared/utils/dates.ts +++ b/src/shared/utils/dates.ts @@ -14,14 +14,21 @@ export const formatTimeFromSeconds = (totalSeconds?: number | null) => { if (totalSeconds === 0) { return '0s' } + if (totalSeconds == null || totalSeconds < 0) { return 'N/A' } - const days = Math.floor(totalSeconds / 86400) - const hours = Math.floor((totalSeconds % 86400) / 3600) - const minutes = Math.floor((totalSeconds % 3600) / 60) - const seconds = Math.floor(totalSeconds % 60) + const SECONDS_PER_DAY = 86400 + const SECONDS_PER_HOUR = 3600 + const SECONDS_PER_MINUTE = 60 + + const days = Math.floor(totalSeconds / SECONDS_PER_DAY) + const hours = Math.floor((totalSeconds % SECONDS_PER_DAY) / SECONDS_PER_HOUR) + const minutes = Math.floor( + (totalSeconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE + ) + const seconds = Math.floor(totalSeconds % SECONDS_PER_MINUTE) const timeParts = [] if (days > 0) { @@ -37,7 +44,7 @@ export const formatTimeFromSeconds = (totalSeconds?: number | null) => { timeParts.push(`${seconds}s`) } - if (timeParts.length === 0 && totalSeconds > 0) { + if (timeParts.length === 0) { return '<1s' } From c422eb20c7a7083bfa77c74544bc1ceeeeb1c94f Mon Sep 17 00:00:00 2001 From: joseph-sentry Date: Thu, 12 Jun 2025 11:26:22 -0400 Subject: [PATCH 3/4] test: add more tests --- src/shared/utils/dates.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/shared/utils/dates.test.ts b/src/shared/utils/dates.test.ts index d0a3972677..063ec3428d 100644 --- a/src/shared/utils/dates.test.ts +++ b/src/shared/utils/dates.test.ts @@ -42,4 +42,16 @@ describe('formatTimeFromSeconds', () => { it('returns the correct time format when totalSeconds is less than 1', () => { expect(formatTimeFromSeconds(0.5)).toBe('<1s') }) + + it('returns "N/A" when totalSeconds is negative', () => { + expect(formatTimeFromSeconds(-1)).toBe('N/A') + }) + + it('returns only minutes when totalSeconds is an exact number of minutes', () => { + expect(formatTimeFromSeconds(120)).toBe('2m') + }) + + it('handles float values that round down', () => { + expect(formatTimeFromSeconds(59.999)).toBe('59s') + }) }) From 3755ba13594bc7da1d31a89450d2779d53b04c0a Mon Sep 17 00:00:00 2001 From: joseph-sentry Date: Thu, 12 Jun 2025 15:34:10 -0400 Subject: [PATCH 4/4] address feedback --- src/shared/utils/dates.ts | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/shared/utils/dates.ts b/src/shared/utils/dates.ts index 2df8acedd2..c3793a11f5 100644 --- a/src/shared/utils/dates.ts +++ b/src/shared/utils/dates.ts @@ -1,5 +1,9 @@ import { formatDistanceToNow, fromUnixTime, parseISO } from 'date-fns' +const SECONDS_PER_DAY = 86400 +const SECONDS_PER_HOUR = 3600 +const SECONDS_PER_MINUTE = 60 + export function formatTimeToNow(date?: string | number | null) { if (!date) return null @@ -11,17 +15,9 @@ export function formatTimeToNow(date?: string | number | null) { } export const formatTimeFromSeconds = (totalSeconds?: number | null) => { - if (totalSeconds === 0) { - return '0s' - } - - if (totalSeconds == null || totalSeconds < 0) { - return 'N/A' - } - - const SECONDS_PER_DAY = 86400 - const SECONDS_PER_HOUR = 3600 - const SECONDS_PER_MINUTE = 60 + if (totalSeconds == null || totalSeconds < 0) return 'N/A' + if (totalSeconds === 0) return '0s' + if (totalSeconds < 1) return '<1s' const days = Math.floor(totalSeconds / SECONDS_PER_DAY) const hours = Math.floor((totalSeconds % SECONDS_PER_DAY) / SECONDS_PER_HOUR) @@ -44,9 +40,5 @@ export const formatTimeFromSeconds = (totalSeconds?: number | null) => { timeParts.push(`${seconds}s`) } - if (timeParts.length === 0) { - return '<1s' - } - return timeParts.join(' ') }