Merge pull request #59 from iib0011/chesterkxng

feat: convert-seconds-to-time, convert-time-to-seconds
This commit is contained in:
Ibrahima G. Coulibaly 2025-03-26 20:02:37 +00:00 committed by GitHub
commit 26ae9e06ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 442 additions and 3 deletions

View file

@ -0,0 +1,50 @@
import { describe, it, expect } from 'vitest';
import { convertSecondsToTime } from './service';
describe('convertSecondsToTime', () => {
it('should convert seconds to a formatted time string', () => {
const result = convertSecondsToTime('3661', true);
expect(result).toBe('01:01:01');
});
it('should handle zero seconds', () => {
const result = convertSecondsToTime('0', true);
expect(result).toBe('00:00:00');
});
it('should handle seconds less than a minute', () => {
const result = convertSecondsToTime('45', true);
expect(result).toBe('00:00:45');
});
it('should handle seconds equal to a full minute', () => {
const result = convertSecondsToTime('60', true);
expect(result).toBe('00:01:00');
});
it('should handle seconds equal to a full hour', () => {
const result = convertSecondsToTime('3600', true);
expect(result).toBe('01:00:00');
});
it('should handle seconds equal to a full hour without padding', () => {
const result = convertSecondsToTime('3600', false);
expect(result).toBe('1:0:0');
});
it('should handle large numbers of seconds with padding', () => {
const result = convertSecondsToTime('7325', true);
expect(result).toBe('02:02:05');
});
it('should handle large numbers of seconds without padding', () => {
const result = convertSecondsToTime('7325', false);
expect(result).toBe('2:2:5');
});
it('should handle numbers of seconds on multilines without padding', () => {
const result = convertSecondsToTime('7325\n3600\n5c\n60', false);
expect(result).toBe('2:2:5\n1:0:0\n\n0:1:0');
});
it('should handle numbers of seconds on multilines with padding', () => {
const result = convertSecondsToTime('7325\n3600\n5c\n60', true);
expect(result).toBe('02:02:05\n01:00:00\n\n00:01:00');
});
});

View file

@ -0,0 +1,111 @@
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 CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import { convertSecondsToTime } from './service';
const initialValues = {
paddingFlag: false
};
type InitialValuesType = typeof initialValues;
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: '1 Second, 1 Minute, 1 Hour',
description:
"In this example, we convert 1 second, 60 seconds, and 3600 seconds to clock format. We don't use the zero-padding option and get three simple output values 0:0:1 for 1 second, 0:1:0 for 60 seconds (1 minute), and 1:0:0 for 3600 seconds (1 hour).",
sampleText: `1
60
3600`,
sampleResult: `0:0:1
0:1:0
1:0:0`,
sampleOptions: { paddingFlag: false }
},
{
title: 'HH:MM:SS Digital Clock',
description:
"In this example, we enable the padding option and output digital clock time in the format HH:MM:SS. The first two integer timestamps don't contain a full minute and the third timestamp doesn't contain a full hour, there we get zeros in the minutes or hours positions in output.",
sampleText: `0
46
890
18305
40271
86399`,
sampleResult: `00:00:00
00:00:46
00:14:50
05:05:05
11:11:11
23:59:59`,
sampleOptions: { paddingFlag: true }
},
{
title: 'More Than a Day',
description:
"The values of all input seconds in this example are greater than the number of seconds in a day (86400 seconds). As our algorithm doesn't limit the time to just 23:59:59 hours, it can find the exact number of hours in large inputs.",
sampleText: `86401
123456
2159999
3600000
101010101`,
sampleResult: `24:00:01
34:17:36
599:59:59
1000:00:00
28058:21:41`,
sampleOptions: { paddingFlag: true }
}
];
export default function SecondsToTime({
title,
longDescription
}: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: string) => {
setResult(convertSecondsToTime(input, optionsValues.paddingFlag));
};
const getGroups: GetGroupsType<InitialValuesType> | null = ({
values,
updateField
}) => [
{
title: 'Time Padding',
component: (
<Box>
<CheckboxWithDesc
onChange={(val) => updateField('paddingFlag', val)}
checked={values.paddingFlag}
title={'Add Padding'}
description={'Add zero padding to hours, minutes, and seconds.'}
/>
</Box>
)
}
];
return (
<ToolContent
title={title}
input={input}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={<ToolTextResult value={result} />}
initialValues={initialValues}
getGroups={getGroups}
setInput={setInput}
compute={compute}
toolInfo={{ title: `What is a ${title}?`, description: longDescription }}
exampleCards={exampleCards}
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('time', {
path: 'convert-seconds-to-time',
name: 'Convert Seconds to Time',
icon: 'fluent-mdl2:time-picker',
description:
'With this browser-based application, you can convert seconds to clock time. Given the seconds input value, it converts them into full hours (H), minutes (M), and seconds (S) and prints them in human-readable clock format (H:M:S or HH:MM:SS) in the output field.',
shortDescription: 'Quicky convert seconds to clock time in H:M:S format.',
keywords: ['convert', 'seconds', 'time', 'clock'],
longDescription:
'This is a quick online utility for converting seconds to H:M:S or HH:MM:SS digital clock time format. It calculates the number of full hours, full minutes, and remaining seconds from the input seconds and outputs regular clock time. For example, 100 seconds is 1 minute and 40 seconds so we get the clock time 00:01:40. To convert seconds to human-readable time we use the Euclidean division algorithm, also known as a division with remainder. If "n" is the input seconds value, then the hours "h" are calculated from the formula n = 3600×h + r, where r is the remainder of dividing n by 3600. Minutes "m" are calculated from the formula r = 60×m + s, and seconds "s" is the remainder of dividing r by 60. For example, if the input n = 4000, then 4000 = 3600×1 + 400. From here we find that the full hours value is 1. Next, the remaining 400 seconds are equal to 60×6 + 40. From here, there are 6 full minutes and 40 more remaining seconds. Thus, we find that 4000 seconds in human time 1 hour, 6 minutes, and 40 seconds. By default, the program outputs the clock time in a padded HH:MM:SS format (i.e. 01:06:40) but you can also disable the padding option and get just H:M:S (i.e. 1:6:40). Timeabulous!',
component: lazy(() => import('./index'))
});

View file

@ -0,0 +1,32 @@
import { containsOnlyDigits } from '@utils/string';
function compute(seconds: string, paddingFlag: boolean): string {
if (!containsOnlyDigits(seconds)) {
return '';
}
const hours = Math.floor(Number(seconds) / 3600);
const minutes = Math.floor((Number(seconds) % 3600) / 60);
const secs = Number(seconds) % 60;
return paddingFlag
? [hours, minutes, secs]
.map((unit) => String(unit).padStart(2, '0')) // Ensures two-digit format
.join(':')
: [hours, minutes, secs].join(':');
}
export function convertSecondsToTime(
input: string,
paddingFlag: boolean
): string {
const result: string[] = [];
const lines = input.split('\n');
lines.forEach((line) => {
const seconds = line.trim();
const time = compute(seconds, paddingFlag);
result.push(time);
});
return result.join('\n');
}

View file

@ -0,0 +1,57 @@
import { describe, it, expect } from 'vitest';
import { convertTimetoSeconds } from './service';
describe('convertSecondsToTime', () => {
it('should convert valid time strings to seconds', () => {
const input = '01:02:03\n00:45:30\n12:00';
const expectedOutput = '3723\n2730\n43200';
expect(convertTimetoSeconds(input)).toBe(expectedOutput);
});
it('should handle single-line input', () => {
const input = '00:01:30';
const expectedOutput = '90';
expect(convertTimetoSeconds(input)).toBe(expectedOutput);
});
it('should throw an error for invalid time format', () => {
const input = '01:02:03\n01:02:03:04';
expect(() => convertTimetoSeconds(input)).toThrow(
'Time contains more than 3 parts on line 2'
);
});
it('should throw an error for non-numeric values (minutes)', () => {
const input = '01:XX:03';
expect(() => convertTimetoSeconds(input)).toThrow(
"Time doesn't contain valid minutes on line 1"
);
});
it('should throw an error for non-numeric values (hours)', () => {
const input = '0x:00:03';
expect(() => convertTimetoSeconds(input)).toThrow(
"Time doesn't contain valid hours on line 1"
);
});
it('should throw an error for non-numeric values (seconds)', () => {
const input = '01:00:0s';
expect(() => convertTimetoSeconds(input)).toThrow(
"Time doesn't contain valid seconds on line 1"
);
});
it('should throw an error for non-numeric values multi lines (seconds)', () => {
const input = '01:00:00\n01:00:0s';
expect(() => convertTimetoSeconds(input)).toThrow(
"Time doesn't contain valid seconds on line 2"
);
});
it('should handle empty input', () => {
const input = '';
const expectedOutput = '';
expect(convertTimetoSeconds(input)).toBe(expectedOutput);
});
});

View file

@ -0,0 +1,99 @@
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 { CardExampleType } from '@components/examples/ToolExamples';
import { convertTimetoSeconds } from './service';
const initialValues = {};
type InitialValuesType = typeof initialValues;
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Multiple Clock Times',
description:
'In this example, we convert multiple clock times to seconds. Each clock time is listed on a new line and the spacing between input times is preserved in the output.',
sampleText: `00:00:00
00:00:01
00:01:00
01:00:00
01:59:59
12:00:00
18:30:30
23:59:59
24:00:00`,
sampleResult: `0
1
60
3600
7199
43200
66630
86399
86400`,
sampleOptions: {}
},
{
title: 'Partial Clock Times',
description:
'This example finds how many seconds there are in clock times that are partially written. Some of the clock times contain just the hours and some others contain just hours and minutes.',
sampleText: `1
1:10
14:44
23`,
sampleResult: `3600
4200
53040
82800`,
sampleOptions: {}
},
{
title: 'Time Beyond 24 Hours',
description:
'In this example, we go beyond the regular 24-hour clock. In fact, we even go beyond 60 minutes and 60 seconds.',
sampleText: `24:00:01
48:00:00
72
00:100:00
100:100:100`,
sampleResult: `86401
172800
259200
6000
366100`,
sampleOptions: {}
}
];
export default function TimeToSeconds({
title,
longDescription
}: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: string) => {
setResult(convertTimetoSeconds(input));
};
return (
<ToolContent
title={title}
input={input}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={<ToolTextResult value={result} />}
initialValues={initialValues}
getGroups={null}
setInput={setInput}
compute={compute}
toolInfo={{ title: `What is a ${title}?`, description: longDescription }}
exampleCards={exampleCards}
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('time', {
path: 'convert-time-to-seconds',
name: 'Convert Time to Seconds',
icon: 'ic:round-timer-10-select',
description:
'With this browser-based application, you can convert clock time provided in hours, minutes, and seconds into just seconds. Given a time in HH:MM:SS format, it calculates HH*3600 + MM*60 + SS and prints this value in the output box. It supports AM/PM time formats as well as clock times beyond 24 hours.',
shortDescription: 'Quickly convert clock time in H:M:S format to seconds.',
keywords: ['convert', 'seconds', 'time', 'clock'],
longDescription:
'This is a quick online utility for calculating how many seconds there are in the given time. When you input a full clock time in the input box (in format H:M:S), it gets split into hours, minutes, and seconds, and using the math formula hours×60×60 plus minutes×60 plus seconds, it finds the seconds. If seconds are missing (format is H:M), then the formula becomes hours×60×60 plus minutes×60. If minutes are also missing, then the formula becomes hours×60×60. As an extra feature, hours, minutes, and seconds are not limited to just 24 hours, 60 minutes, and 60 seconds. You can use any hours value, any minutes value, and any seconds value. For example, the input time "72:00:00" will find the number of seconds in three days (72 hours is 3×24 hours) and the input time "0:1000:0" will find seconds in 1000 minutes. Timeabulous!',
component: lazy(() => import('./index'))
});

View file

@ -0,0 +1,53 @@
import { containsOnlyDigits } from '@utils/string';
function recursiveTimeToSeconds(
timeArray: string[],
index: number = 0
): number {
if (index >= timeArray.length) {
return 0;
}
const multipliers = [3600, 60, 1];
return (
Number(timeArray[index]) * multipliers[index] +
recursiveTimeToSeconds(timeArray, index + 1)
);
}
function compute(timeArray: string[], lineNumber: number): string {
if (timeArray[0] == '') {
return '';
}
if (timeArray.length > 3) {
throw new Error(`Time contains more than 3 parts on line ${lineNumber}`);
}
const normalizedArray = [...timeArray, '0', '0'];
normalizedArray.forEach((time, index) => {
if (!containsOnlyDigits(time)) {
throw new Error(
`Time doesn't contain valid ${
['hours', 'minutes', 'seconds'][index]
} on line ${lineNumber}`
);
}
});
return recursiveTimeToSeconds(timeArray).toString();
}
export function convertTimetoSeconds(input: string): string {
const result: string[] = [];
const lines = input.split('\n');
lines.forEach((line, index) => {
const timeArray = line.split(':');
const seconds = compute(timeArray, index + 1);
result.push(seconds);
});
return result.join('\n');
}

View file

@ -1,4 +1,11 @@
import { tool as daysDoHours } from './convert-days-to-hours/meta';
import { tool as hoursToDays } from './convert-hours-to-days/meta';
import { tool as convertSecondsToTime } from './convert-seconds-to-time/meta';
import { tool as convertTimetoSeconds } from './convert-time-to-seconds/meta';
export const timeTools = [daysDoHours, hoursToDays];
export const timeTools = [
daysDoHours,
hoursToDays,
convertSecondsToTime,
convertTimetoSeconds
];

View file

@ -41,8 +41,8 @@ export function reverseString(input: string): string {
/**
* Checks if the input string contains only digits.
* @param input - The string to validate.
* @returns True if the input contains only digits, false otherwise.
* @returns True if the input contains only digits including float, false otherwise.
*/
export function containsOnlyDigits(input: string): boolean {
return /^-?\d+(\.\d+)?$/.test(input.trim());
return /^\d+(\.\d+)?$/.test(input.trim());
}