mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-18 21:49:31 +02:00
251 lines
7.0 KiB
TypeScript
251 lines
7.0 KiB
TypeScript
import { Box, Paper, Typography } from '@mui/material';
|
|
import React, { useState } from 'react';
|
|
import ToolContent from '@components/ToolContent';
|
|
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
|
|
import SelectWithDesc from '@components/options/SelectWithDesc';
|
|
import {
|
|
calculateTimeBetweenDates,
|
|
formatTimeWithLargestUnit,
|
|
getTimeWithTimezone,
|
|
unitHierarchy
|
|
} from './service';
|
|
import * as Yup from 'yup';
|
|
import { CardExampleType } from '@components/examples/ToolExamples';
|
|
|
|
type TimeUnit =
|
|
| 'milliseconds'
|
|
| 'seconds'
|
|
| 'minutes'
|
|
| 'hours'
|
|
| 'days'
|
|
| 'months'
|
|
| 'years';
|
|
|
|
type InitialValuesType = {
|
|
startDate: string;
|
|
startTime: string;
|
|
endDate: string;
|
|
endTime: string;
|
|
startTimezone: string;
|
|
endTimezone: string;
|
|
};
|
|
|
|
const initialValues: InitialValuesType = {
|
|
startDate: new Date().toISOString().split('T')[0],
|
|
startTime: '00:00',
|
|
endDate: new Date().toISOString().split('T')[0],
|
|
endTime: '12:00',
|
|
startTimezone: 'local',
|
|
endTimezone: 'local'
|
|
};
|
|
|
|
const validationSchema = Yup.object({
|
|
startDate: Yup.string().required('Start date is required'),
|
|
startTime: Yup.string().required('Start time is required'),
|
|
endDate: Yup.string().required('End date is required'),
|
|
endTime: Yup.string().required('End time is required'),
|
|
startTimezone: Yup.string(),
|
|
endTimezone: Yup.string()
|
|
});
|
|
|
|
const timezoneOptions = [
|
|
{ value: 'local', label: 'Local Time' },
|
|
...Intl.supportedValuesOf('timeZone')
|
|
.map((tz) => {
|
|
const formatter = new Intl.DateTimeFormat('en', {
|
|
timeZone: tz,
|
|
timeZoneName: 'shortOffset'
|
|
});
|
|
|
|
const offset =
|
|
formatter
|
|
.formatToParts(new Date())
|
|
.find((part) => part.type === 'timeZoneName')?.value || '';
|
|
|
|
return {
|
|
value: offset.replace('UTC', 'GMT'),
|
|
label: `${offset.replace('UTC', 'GMT')} (${tz})`
|
|
};
|
|
})
|
|
.sort((a, b) =>
|
|
a.value.localeCompare(b.value, undefined, { numeric: true })
|
|
)
|
|
];
|
|
|
|
const exampleCards: CardExampleType<InitialValuesType>[] = [
|
|
{
|
|
title: 'One Year Difference',
|
|
description: 'Calculate the time between dates that are one year apart',
|
|
sampleOptions: {
|
|
startDate: '2023-01-01',
|
|
startTime: '12:00',
|
|
endDate: '2024-01-01',
|
|
endTime: '12:00',
|
|
startTimezone: 'local',
|
|
endTimezone: 'local'
|
|
},
|
|
sampleResult: '1 year'
|
|
},
|
|
{
|
|
title: 'Different Timezones',
|
|
description: 'Calculate the time difference between New York and London',
|
|
sampleOptions: {
|
|
startDate: '2023-01-01',
|
|
startTime: '12:00',
|
|
endDate: '2023-01-01',
|
|
endTime: '12:00',
|
|
startTimezone: 'GMT-5',
|
|
endTimezone: 'GMT'
|
|
},
|
|
sampleResult: '5 hours'
|
|
},
|
|
{
|
|
title: 'Detailed Time Breakdown',
|
|
description: 'Show a detailed breakdown of a time difference',
|
|
sampleOptions: {
|
|
startDate: '2023-01-01',
|
|
startTime: '09:30',
|
|
endDate: '2023-01-03',
|
|
endTime: '14:45',
|
|
startTimezone: 'local',
|
|
endTimezone: 'local'
|
|
},
|
|
sampleResult: '2 days, 5 hours, 15 minutes'
|
|
}
|
|
];
|
|
|
|
export default function TimeBetweenDates() {
|
|
const [result, setResult] = useState<string>('');
|
|
|
|
return (
|
|
<ToolContent
|
|
title="Time Between Dates"
|
|
inputComponent={null}
|
|
resultComponent={
|
|
result ? (
|
|
<Paper
|
|
elevation={3}
|
|
sx={{
|
|
p: 3,
|
|
borderLeft: '5px solid',
|
|
borderColor: 'primary.main',
|
|
bgcolor: 'background.paper',
|
|
maxWidth: '100%',
|
|
mx: 'auto'
|
|
}}
|
|
>
|
|
<Typography
|
|
variant="h4"
|
|
align="center"
|
|
sx={{ fontWeight: 'bold', color: 'primary.main' }}
|
|
>
|
|
{result}
|
|
</Typography>
|
|
</Paper>
|
|
) : null
|
|
}
|
|
initialValues={initialValues}
|
|
validationSchema={validationSchema}
|
|
exampleCards={exampleCards}
|
|
toolInfo={{
|
|
title: 'Time Between Dates Calculator',
|
|
description:
|
|
'Calculate the exact time difference between two dates and times, with support for different timezones. This tool provides a detailed breakdown of the time difference in various units (years, months, days, hours, minutes, and seconds).'
|
|
}}
|
|
getGroups={({ values, updateField }) => [
|
|
{
|
|
title: 'Start Date & Time',
|
|
component: (
|
|
<Box>
|
|
<TextFieldWithDesc
|
|
description="Start Date"
|
|
value={values.startDate}
|
|
onOwnChange={(val) => updateField('startDate', val)}
|
|
type="date"
|
|
/>
|
|
<TextFieldWithDesc
|
|
description="Start Time"
|
|
value={values.startTime}
|
|
onOwnChange={(val) => updateField('startTime', val)}
|
|
type="time"
|
|
/>
|
|
<SelectWithDesc
|
|
description="Start Timezone"
|
|
selected={values.startTimezone}
|
|
onChange={(val: string) => updateField('startTimezone', val)}
|
|
options={timezoneOptions}
|
|
/>
|
|
</Box>
|
|
)
|
|
},
|
|
{
|
|
title: 'End Date & Time',
|
|
component: (
|
|
<Box>
|
|
<TextFieldWithDesc
|
|
description="End Date"
|
|
value={values.endDate}
|
|
onOwnChange={(val) => updateField('endDate', val)}
|
|
type="date"
|
|
/>
|
|
<TextFieldWithDesc
|
|
description="End Time"
|
|
value={values.endTime}
|
|
onOwnChange={(val) => updateField('endTime', val)}
|
|
type="time"
|
|
/>
|
|
<SelectWithDesc
|
|
description="End Timezone"
|
|
selected={values.endTimezone}
|
|
onChange={(val: string) => updateField('endTimezone', val)}
|
|
options={timezoneOptions}
|
|
/>
|
|
</Box>
|
|
)
|
|
}
|
|
]}
|
|
compute={(values) => {
|
|
try {
|
|
const startDateTime = getTimeWithTimezone(
|
|
values.startDate,
|
|
values.startTime,
|
|
values.startTimezone
|
|
);
|
|
|
|
const endDateTime = getTimeWithTimezone(
|
|
values.endDate,
|
|
values.endTime,
|
|
values.endTimezone
|
|
);
|
|
|
|
// Calculate time difference
|
|
const difference = calculateTimeBetweenDates(
|
|
startDateTime,
|
|
endDateTime
|
|
);
|
|
|
|
// Auto-determine the best unit to display based on the time difference
|
|
const bestUnit: TimeUnit =
|
|
unitHierarchy.find((unit) => difference[unit] > 0) ||
|
|
'milliseconds';
|
|
|
|
const formattedDifference = formatTimeWithLargestUnit(
|
|
difference,
|
|
bestUnit
|
|
);
|
|
|
|
setResult(formattedDifference);
|
|
} catch (error) {
|
|
setResult(
|
|
`Error: ${
|
|
error instanceof Error
|
|
? error.message
|
|
: 'Failed to calculate time difference'
|
|
}`
|
|
);
|
|
}
|
|
}}
|
|
/>
|
|
);
|
|
}
|