From b1f63a320779c3098fd535d3d967dfaeaeef4b99 Mon Sep 17 00:00:00 2001 From: Mike Bricknell-Barlow Date: Tue, 2 Dec 2025 12:52:52 +0000 Subject: [PATCH] Add tool to convert human time to decimal time --- public/locales/en/time.json | 6 ++ .../convert-time-to-decimal.service.test.ts | 40 +++++++++++ .../time/convert-time-to-decimal/index.tsx | 72 +++++++++++++++++++ .../time/convert-time-to-decimal/meta.ts | 15 ++++ .../time/convert-time-to-decimal/service.ts | 24 +++++++ .../time/convert-time-to-decimal/types.ts | 3 + src/pages/tools/time/index.ts | 4 +- 7 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 src/pages/tools/time/convert-time-to-decimal/convert-time-to-decimal.service.test.ts create mode 100644 src/pages/tools/time/convert-time-to-decimal/index.tsx create mode 100644 src/pages/tools/time/convert-time-to-decimal/meta.ts create mode 100644 src/pages/tools/time/convert-time-to-decimal/service.ts create mode 100644 src/pages/tools/time/convert-time-to-decimal/types.ts diff --git a/public/locales/en/time.json b/public/locales/en/time.json index 6bfb88e..9398b45 100644 --- a/public/locales/en/time.json +++ b/public/locales/en/time.json @@ -113,5 +113,11 @@ "zeroPaddingDescription": "Make all time components always be two digits wide.", "zeroPrintDescription": "Display the dropped parts as zero values \"00\".", "zeroPrintTruncatedParts": "Zero-print Truncated Parts" + }, + "convertTimeToDecimal": { + "title": "Convert time to decimal", + "description": "Convert formatted length of time (HH:MM:SS) to decimal format, e.g. 3.43 hours.", + "shortDescription": "Convert human time to decimal time", + "longDescription": "Convert formatted length of time (HH:MM:SS) to decimal format, e.g. 3.43 hours." } } diff --git a/src/pages/tools/time/convert-time-to-decimal/convert-time-to-decimal.service.test.ts b/src/pages/tools/time/convert-time-to-decimal/convert-time-to-decimal.service.test.ts new file mode 100644 index 0000000..9ca6839 --- /dev/null +++ b/src/pages/tools/time/convert-time-to-decimal/convert-time-to-decimal.service.test.ts @@ -0,0 +1,40 @@ +import { expect, describe, it } from 'vitest'; +import { convertTimeToDecimal } from './service'; + +describe('convert-time-to-decimal', () => { + it('should convert time to decimal with default decimal places', () => { + const input = '31:23:59'; + const result = convertTimeToDecimal(input, { decimalPlaces: '6' }); + expect(result).toBe('31.399722'); + }); + + it('should convert time to decimal with specified decimal places', () => { + const input = '31:23:59'; + const result = convertTimeToDecimal(input, { decimalPlaces: '10' }); + expect(result).toBe('31.3997222222'); + }); + + it('should convert time to decimal with supplied format of HH:MM:SS', () => { + const input = '13:25:30'; + const result = convertTimeToDecimal(input, { decimalPlaces: '6' }); + expect(result).toBe('13.425000'); + }); + + it('should convert time to decimal with supplied format of HH:MM', () => { + const input = '13:25'; + const result = convertTimeToDecimal(input, { decimalPlaces: '6' }); + expect(result).toBe('13.416667'); + }); + + it('should convert time to decimal with supplied format of HH:MM:', () => { + const input = '13:25'; + const result = convertTimeToDecimal(input, { decimalPlaces: '6' }); + expect(result).toBe('13.416667'); + }); + + it('should convert time to decimal with supplied format of HH.MM.SS', () => { + const input = '13.25.30'; + const result = convertTimeToDecimal(input, { decimalPlaces: '6' }); + expect(result).toBe('13.425000'); + }); +}); diff --git a/src/pages/tools/time/convert-time-to-decimal/index.tsx b/src/pages/tools/time/convert-time-to-decimal/index.tsx new file mode 100644 index 0000000..1e1c567 --- /dev/null +++ b/src/pages/tools/time/convert-time-to-decimal/index.tsx @@ -0,0 +1,72 @@ +import { Box } from '@mui/material'; +import React, { useState } from 'react'; +import ToolContent from '@components/ToolContent'; +import { ToolComponentProps } from '@tools/defineTool'; +import ToolTextInput from '@components/input/ToolTextInput'; +import ToolTextResult from '@components/result/ToolTextResult'; +import { GetGroupsType } from '@components/options/ToolOptions'; +import { CardExampleType } from '@components/examples/ToolExamples'; +import { convertTimeToDecimal } from './service'; +import { InitialValuesType } from './types'; +import TextFieldWithDesc from '@components/options/TextFieldWithDesc'; + +const initialValues: InitialValuesType = { + decimalPlaces: '6' +}; + +const exampleCards: CardExampleType[] = [ + { + title: 'Convert time to decimal', + description: + 'This example shows how to convert a formatted time (HH:MM:SS) to a decimal version.', + sampleText: '31:23:59', + sampleResult: `31.399722`, + sampleOptions: { + decimalPlaces: '6' + } + } +]; +export default function ConvertTimeToDecimal({ + title, + longDescription +}: ToolComponentProps) { + const [input, setInput] = useState(''); + const [result, setResult] = useState(''); + + const compute = (values: InitialValuesType, input: string) => { + setResult(convertTimeToDecimal(input, values)); + }; + + const getGroups: GetGroupsType | null = ({ + values, + updateField + }) => [ + { + title: 'Decimal places', + component: ( + + updateField('decimalPlaces', val)} + type={'text'} + /> + + ) + } + ]; + return ( + } + resultComponent={} + initialValues={initialValues} + exampleCards={exampleCards} + getGroups={getGroups} + setInput={setInput} + compute={compute} + toolInfo={{ title: `What is a ${title}?`, description: longDescription }} + /> + ); +} diff --git a/src/pages/tools/time/convert-time-to-decimal/meta.ts b/src/pages/tools/time/convert-time-to-decimal/meta.ts new file mode 100644 index 0000000..f7f8624 --- /dev/null +++ b/src/pages/tools/time/convert-time-to-decimal/meta.ts @@ -0,0 +1,15 @@ +import { defineTool } from '@tools/defineTool'; +import { lazy } from 'react'; + +export const tool = defineTool('time', { + i18n: { + name: 'time:convertTimeToDecimal.title', + description: 'time:convertTimeToDecimal.description', + shortDescription: 'time:convertTimeToDecimal.shortDescription', + longDescription: 'time:convertTimeToDecimal.longDescription' + }, + path: 'convert-time-to-decimal', + icon: 'material-symbols:schedule', + keywords: ['convert', 'time', 'to', 'decimal'], + component: lazy(() => import('./index')) +}); diff --git a/src/pages/tools/time/convert-time-to-decimal/service.ts b/src/pages/tools/time/convert-time-to-decimal/service.ts new file mode 100644 index 0000000..f7b8dab --- /dev/null +++ b/src/pages/tools/time/convert-time-to-decimal/service.ts @@ -0,0 +1,24 @@ +import { InitialValuesType } from './types'; + +export function convertTimeToDecimal( + input: string, + options: InitialValuesType +): string { + if (!input || (!input.includes(':') && !input.includes('.'))) { + return ''; + } + + let splitTime = input.split(/[.:]/); + + let hours = parseInt(splitTime[0]); + let minutes = parseInt(splitTime[1]); + let seconds = splitTime[2] ? parseInt(splitTime[2]) : 0; + + let decimalTime = hours + minutes / 60; + + if (seconds !== 0) { + decimalTime += seconds / 3600; + } + + return decimalTime.toFixed(parseInt(options.decimalPlaces)).toString(); +} diff --git a/src/pages/tools/time/convert-time-to-decimal/types.ts b/src/pages/tools/time/convert-time-to-decimal/types.ts new file mode 100644 index 0000000..f4bf30a --- /dev/null +++ b/src/pages/tools/time/convert-time-to-decimal/types.ts @@ -0,0 +1,3 @@ +export type InitialValuesType = { + decimalPlaces: string; +}; diff --git a/src/pages/tools/time/index.ts b/src/pages/tools/time/index.ts index a98d27e..fbbcff4 100644 --- a/src/pages/tools/time/index.ts +++ b/src/pages/tools/time/index.ts @@ -1,3 +1,4 @@ +import { tool as timeConvertTimeToDecimal } from './convert-time-to-decimal/meta'; import { tool as timeConvertUnixToDate } from './convert-unix-to-date/meta'; import { tool as timeCrontabGuru } from './crontab-guru/meta'; import { tool as timeBetweenDates } from './time-between-dates/meta'; @@ -17,5 +18,6 @@ export const timeTools = [ timeBetweenDates, timeCrontabGuru, checkLeapYear, - timeConvertUnixToDate + timeConvertUnixToDate, + timeConvertTimeToDecimal ];