diff --git a/services/web/frontend/js/shared/utils/time.ts b/services/web/frontend/js/shared/utils/time.ts index 77a9855287..07936764d2 100644 --- a/services/web/frontend/js/shared/utils/time.ts +++ b/services/web/frontend/js/shared/utils/time.ts @@ -1,28 +1,37 @@ import { TFunction } from 'i18next' +export function secondsToHoursAndMinutes(seconds: number): { + hours: number + minutes: number +} { + // round up: the caller tells the user how long to wait, so never understate + const totalMinutes = Math.ceil(seconds / 60) + return { + hours: Math.floor(totalMinutes / 60), + minutes: totalMinutes % 60, + } +} + export function formatSecondsToHoursAndMinutes( t: TFunction, seconds: number ): string { - // round up: the caller tells the user how long to wait, so never understate - const totalMinutes = Math.ceil(seconds / 60) - const hrs = Math.floor(totalMinutes / 60) - const mins = totalMinutes % 60 + const { hours, minutes } = secondsToHoursAndMinutes(seconds) const parts = [] - if (hrs > 0) { - parts.push(t('time_hour', { count: hrs })) + if (hours > 0) { + parts.push(t('time_hour', { count: hours })) } - if (hrs > 0 && mins > 0) { + if (hours > 0 && minutes > 0) { parts.push(t('time_and')) } - if (mins > 0) { + if (minutes > 0) { parts.push( t('time_minute', { - count: mins, + count: minutes, }) ) } diff --git a/services/web/test/frontend/shared/utils/time.test.ts b/services/web/test/frontend/shared/utils/time.test.ts index 175ec54b9e..768c90d37b 100644 --- a/services/web/test/frontend/shared/utils/time.test.ts +++ b/services/web/test/frontend/shared/utils/time.test.ts @@ -1,6 +1,9 @@ import { expect } from 'chai' import { TFunction } from 'i18next' -import { formatSecondsToHoursAndMinutes } from '@/shared/utils/time' +import { + formatSecondsToHoursAndMinutes, + secondsToHoursAndMinutes, +} from '@/shared/utils/time' // stands in for i18next, echoing the key and its count const t = ((key: string, options?: { count?: number }) => @@ -62,3 +65,33 @@ describe('formatSecondsToHoursAndMinutes', function () { ) }) }) + +describe('secondsToHoursAndMinutes', function () { + it('rounds a part-minute up - 50s', function () { + expect(secondsToHoursAndMinutes(50)).to.deep.equal({ + hours: 0, + minutes: 1, + }) + }) + + it('rounds a part-minute up - 1m 59s', function () { + expect(secondsToHoursAndMinutes(ONE_MINUTE_IN_SECONDS + 59)).to.deep.equal({ + hours: 0, + minutes: 2, + }) + }) + + it('carries whole minutes into hours without a 60 - 1h', function () { + expect(secondsToHoursAndMinutes(ONE_HOUR_IN_SECONDS)).to.deep.equal({ + hours: 1, + minutes: 0, + }) + }) + + it('is zero for no remaining time', function () { + expect(secondsToHoursAndMinutes(0)).to.deep.equal({ + hours: 0, + minutes: 0, + }) + }) +})