Skip to content

Commit c619e4b

Browse files
authored
Merge pull request #61 from TheLukasHenry/days-calculator-#51
added time between 2 dates #51
2 parents 4b2d38c + 6ac0f24 commit c619e4b

File tree

8 files changed

+644
-124
lines changed

8 files changed

+644
-124
lines changed

.idea/workspace.xml

Lines changed: 136 additions & 123 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/pages/tools/time/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1+
import { tool as timeBetweenDates } from './time-between-dates/meta';
12
import { tool as daysDoHours } from './convert-days-to-hours/meta';
23
import { tool as hoursToDays } from './convert-hours-to-days/meta';
34
import { tool as convertSecondsToTime } from './convert-seconds-to-time/meta';
45
import { tool as convertTimetoSeconds } from './convert-time-to-seconds/meta';
56
import { tool as truncateClockTime } from './truncate-clock-time/meta';
67

8+
79
export const timeTools = [
810
daysDoHours,
911
hoursToDays,
1012
convertSecondsToTime,
1113
convertTimetoSeconds,
12-
truncateClockTime
14+
truncateClockTime,
15+
timeBetweenDates
1316
];
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
import { Box, Paper, Typography } from '@mui/material';
2+
import React, { useState } from 'react';
3+
import ToolContent from '@components/ToolContent';
4+
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
5+
import SelectWithDesc from '@components/options/SelectWithDesc';
6+
import {
7+
calculateTimeBetweenDates,
8+
formatTimeWithLargestUnit,
9+
getTimeWithTimezone,
10+
unitHierarchy
11+
} from './service';
12+
import * as Yup from 'yup';
13+
import { CardExampleType } from '@components/examples/ToolExamples';
14+
15+
type TimeUnit =
16+
| 'milliseconds'
17+
| 'seconds'
18+
| 'minutes'
19+
| 'hours'
20+
| 'days'
21+
| 'months'
22+
| 'years';
23+
24+
type InitialValuesType = {
25+
startDate: string;
26+
startTime: string;
27+
endDate: string;
28+
endTime: string;
29+
startTimezone: string;
30+
endTimezone: string;
31+
};
32+
33+
const initialValues: InitialValuesType = {
34+
startDate: new Date().toISOString().split('T')[0],
35+
startTime: '00:00',
36+
endDate: new Date().toISOString().split('T')[0],
37+
endTime: '12:00',
38+
startTimezone: 'local',
39+
endTimezone: 'local'
40+
};
41+
42+
const validationSchema = Yup.object({
43+
startDate: Yup.string().required('Start date is required'),
44+
startTime: Yup.string().required('Start time is required'),
45+
endDate: Yup.string().required('End date is required'),
46+
endTime: Yup.string().required('End time is required'),
47+
startTimezone: Yup.string(),
48+
endTimezone: Yup.string()
49+
});
50+
51+
const timezoneOptions = [
52+
{ value: 'local', label: 'Local Time' },
53+
...Intl.supportedValuesOf('timeZone')
54+
.map((tz) => {
55+
const formatter = new Intl.DateTimeFormat('en', {
56+
timeZone: tz,
57+
timeZoneName: 'shortOffset'
58+
});
59+
60+
const offset =
61+
formatter
62+
.formatToParts(new Date())
63+
.find((part) => part.type === 'timeZoneName')?.value || '';
64+
65+
return {
66+
value: offset.replace('UTC', 'GMT'),
67+
label: `${offset.replace('UTC', 'GMT')} (${tz})`
68+
};
69+
})
70+
.sort((a, b) =>
71+
a.value.localeCompare(b.value, undefined, { numeric: true })
72+
)
73+
];
74+
75+
const exampleCards: CardExampleType<InitialValuesType>[] = [
76+
{
77+
title: 'One Year Difference',
78+
description: 'Calculate the time between dates that are one year apart',
79+
sampleOptions: {
80+
startDate: '2023-01-01',
81+
startTime: '12:00',
82+
endDate: '2024-01-01',
83+
endTime: '12:00',
84+
startTimezone: 'local',
85+
endTimezone: 'local'
86+
},
87+
sampleResult: '1 year'
88+
},
89+
{
90+
title: 'Different Timezones',
91+
description: 'Calculate the time difference between New York and London',
92+
sampleOptions: {
93+
startDate: '2023-01-01',
94+
startTime: '12:00',
95+
endDate: '2023-01-01',
96+
endTime: '12:00',
97+
startTimezone: 'GMT-5',
98+
endTimezone: 'GMT'
99+
},
100+
sampleResult: '5 hours'
101+
},
102+
{
103+
title: 'Detailed Time Breakdown',
104+
description: 'Show a detailed breakdown of a time difference',
105+
sampleOptions: {
106+
startDate: '2023-01-01',
107+
startTime: '09:30',
108+
endDate: '2023-01-03',
109+
endTime: '14:45',
110+
startTimezone: 'local',
111+
endTimezone: 'local'
112+
},
113+
sampleResult: '2 days, 5 hours, 15 minutes'
114+
}
115+
];
116+
117+
export default function TimeBetweenDates() {
118+
const [result, setResult] = useState<string>('');
119+
120+
return (
121+
<ToolContent
122+
title="Time Between Dates"
123+
inputComponent={null}
124+
resultComponent={
125+
result ? (
126+
<Paper
127+
elevation={3}
128+
sx={{
129+
p: 3,
130+
borderLeft: '5px solid',
131+
borderColor: 'primary.main',
132+
bgcolor: 'background.paper',
133+
maxWidth: '100%',
134+
mx: 'auto'
135+
}}
136+
>
137+
<Typography
138+
variant="h4"
139+
align="center"
140+
sx={{ fontWeight: 'bold', color: 'primary.main' }}
141+
>
142+
{result}
143+
</Typography>
144+
</Paper>
145+
) : null
146+
}
147+
initialValues={initialValues}
148+
validationSchema={validationSchema}
149+
exampleCards={exampleCards}
150+
toolInfo={{
151+
title: 'Time Between Dates Calculator',
152+
description:
153+
'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).'
154+
}}
155+
getGroups={({ values, updateField }) => [
156+
{
157+
title: 'Start Date & Time',
158+
component: (
159+
<Box>
160+
<TextFieldWithDesc
161+
description="Start Date"
162+
value={values.startDate}
163+
onOwnChange={(val) => updateField('startDate', val)}
164+
type="date"
165+
/>
166+
<TextFieldWithDesc
167+
description="Start Time"
168+
value={values.startTime}
169+
onOwnChange={(val) => updateField('startTime', val)}
170+
type="time"
171+
/>
172+
<SelectWithDesc
173+
description="Start Timezone"
174+
selected={values.startTimezone}
175+
onChange={(val: string) => updateField('startTimezone', val)}
176+
options={timezoneOptions}
177+
/>
178+
</Box>
179+
)
180+
},
181+
{
182+
title: 'End Date & Time',
183+
component: (
184+
<Box>
185+
<TextFieldWithDesc
186+
description="End Date"
187+
value={values.endDate}
188+
onOwnChange={(val) => updateField('endDate', val)}
189+
type="date"
190+
/>
191+
<TextFieldWithDesc
192+
description="End Time"
193+
value={values.endTime}
194+
onOwnChange={(val) => updateField('endTime', val)}
195+
type="time"
196+
/>
197+
<SelectWithDesc
198+
description="End Timezone"
199+
selected={values.endTimezone}
200+
onChange={(val: string) => updateField('endTimezone', val)}
201+
options={timezoneOptions}
202+
/>
203+
</Box>
204+
)
205+
}
206+
]}
207+
compute={(values) => {
208+
try {
209+
const startDateTime = getTimeWithTimezone(
210+
values.startDate,
211+
values.startTime,
212+
values.startTimezone
213+
);
214+
215+
const endDateTime = getTimeWithTimezone(
216+
values.endDate,
217+
values.endTime,
218+
values.endTimezone
219+
);
220+
221+
// Calculate time difference
222+
const difference = calculateTimeBetweenDates(
223+
startDateTime,
224+
endDateTime
225+
);
226+
227+
// Auto-determine the best unit to display based on the time difference
228+
const bestUnit: TimeUnit =
229+
unitHierarchy.find((unit) => difference[unit] > 0) ||
230+
'milliseconds';
231+
232+
const formattedDifference = formatTimeWithLargestUnit(
233+
difference,
234+
bestUnit
235+
);
236+
237+
setResult(formattedDifference);
238+
} catch (error) {
239+
setResult(
240+
`Error: ${
241+
error instanceof Error
242+
? error.message
243+
: 'Failed to calculate time difference'
244+
}`
245+
);
246+
}
247+
}}
248+
/>
249+
);
250+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { defineTool } from '@tools/defineTool';
2+
import { lazy } from 'react';
3+
4+
export const tool = defineTool('time', {
5+
name: 'Time Between Dates',
6+
path: 'time-between-dates',
7+
icon: 'mdi:calendar-clock',
8+
description:
9+
'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).',
10+
shortDescription:
11+
'Calculate the precise time duration between two dates with timezone support.',
12+
keywords: [
13+
'time',
14+
'dates',
15+
'difference',
16+
'duration',
17+
'calculator',
18+
'timezones',
19+
'interval'
20+
],
21+
component: lazy(() => import('./index'))
22+
});

0 commit comments

Comments
 (0)