Merge pull request #2 from CryoRig/copilot/fix-1

Add Time converter to epoch and reverse
This commit is contained in:
CryoRig 2025-07-10 09:57:59 +02:00 committed by GitHub
commit 9c45f2492a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 482 additions and 0 deletions

View file

@ -0,0 +1,193 @@
import { describe, it, expect } from 'vitest';
import { convertDateToEpoch, convertEpochToDate } from './service';
describe('convertDateToEpoch', () => {
it('should convert ISO 8601 date strings to epoch', () => {
const input = '2023-01-01T00:00:00Z\n2023-12-31T23:59:59Z';
const result = convertDateToEpoch(input);
const lines = result.split('\n');
expect(lines[0]).toBe('1672531200'); // 2023-01-01 00:00:00 UTC
expect(lines[1]).toBe('1704067199'); // 2023-12-31 23:59:59 UTC
});
it('should convert YYYY-MM-DD date format to epoch', () => {
const input = '2023-01-01\n2023-06-15';
const result = convertDateToEpoch(input);
const lines = result.split('\n');
expect(lines[0]).toBe('1672531200'); // 2023-01-01 00:00:00 UTC
expect(lines[1]).toBe('1686787200'); // 2023-06-15 00:00:00 UTC
});
it('should convert YYYY-MM-DD HH:mm:ss format to epoch', () => {
const input = '2023-01-01 12:30:45';
const result = convertDateToEpoch(input);
expect(result).toBe('1672576245'); // 2023-01-01 12:30:45 UTC
});
it('should convert MM/DD/YYYY format to epoch', () => {
const input = '01/01/2023\n12/31/2023';
const result = convertDateToEpoch(input);
const lines = result.split('\n');
expect(lines[0]).toBe('1672531200'); // 2023-01-01 00:00:00 UTC
expect(lines[1]).toBe('1703980800'); // 2023-12-31 00:00:00 UTC
});
it('should convert DD/MM/YYYY format to epoch', () => {
const input = '15/06/2023';
const result = convertDateToEpoch(input);
expect(result).toBe('1686787200'); // 2023-06-15 00:00:00 UTC
});
it('should handle already existing epoch timestamps', () => {
const input = '1672531200\n1704067199';
const result = convertDateToEpoch(input);
expect(result).toBe('1672531200\n1704067199');
});
it('should handle empty lines', () => {
const input = '2023-01-01\n\n2023-12-31';
const result = convertDateToEpoch(input);
const lines = result.split('\n');
expect(lines[0]).toBe('1672531200');
expect(lines[1]).toBe('');
expect(lines[2]).toBe('1703980800');
});
it('should handle empty input', () => {
const input = '';
const result = convertDateToEpoch(input);
expect(result).toBe('');
});
it('should throw error for invalid date format', () => {
const input = 'invalid-date-format';
expect(() => convertDateToEpoch(input)).toThrow(
'Invalid date format on line 1: "invalid-date-format"'
);
});
it('should throw error for invalid date on specific line', () => {
const input = '2023-01-01\ninvalid-date\n2023-12-31';
expect(() => convertDateToEpoch(input)).toThrow(
'Invalid date format on line 2: "invalid-date"'
);
});
it('should handle mixed date formats', () => {
const input = '2023-01-01T00:00:00Z\n01/15/2023\n2023-06-15 12:30:00';
const result = convertDateToEpoch(input);
const lines = result.split('\n');
expect(lines[0]).toBe('1672531200'); // ISO format
expect(lines[1]).toBe('1673740800'); // MM/DD/YYYY format
expect(lines[2]).toBe('1686832200'); // YYYY-MM-DD HH:mm:ss format
});
it('should handle JavaScript date string format', () => {
const input = 'Sun Jan 01 2023 00:00:00';
const result = convertDateToEpoch(input);
expect(result).toBe('1672531200');
});
it('should convert date with milliseconds correctly', () => {
const input = '2023-01-01T00:00:00.000Z';
const result = convertDateToEpoch(input);
expect(result).toBe('1672531200');
});
});
describe('convertEpochToDate', () => {
it('should convert epoch timestamps to human-readable dates', () => {
const input = '1672531200\n1704067199';
const result = convertEpochToDate(input);
const lines = result.split('\n');
expect(lines[0]).toBe('2023-01-01 00:00:00 UTC');
expect(lines[1]).toBe('2023-12-31 23:59:59 UTC');
});
it('should convert single epoch timestamp', () => {
const input = '1672531200';
const result = convertEpochToDate(input);
expect(result).toBe('2023-01-01 00:00:00 UTC');
});
it('should handle epoch timestamp 0', () => {
const input = '0';
const result = convertEpochToDate(input);
expect(result).toBe('1970-01-01 00:00:00 UTC');
});
it('should handle empty lines', () => {
const input = '1672531200\n\n1704067199';
const result = convertEpochToDate(input);
const lines = result.split('\n');
expect(lines[0]).toBe('2023-01-01 00:00:00 UTC');
expect(lines[1]).toBe('');
expect(lines[2]).toBe('2023-12-31 23:59:59 UTC');
});
it('should handle empty input', () => {
const input = '';
const result = convertEpochToDate(input);
expect(result).toBe('');
});
it('should throw error for invalid epoch timestamp', () => {
const input = 'invalid-epoch';
expect(() => convertEpochToDate(input)).toThrow(
'Invalid epoch timestamp on line 1: "invalid-epoch"'
);
});
it('should throw error for negative epoch timestamp', () => {
const input = '-1672531200';
expect(() => convertEpochToDate(input)).toThrow(
'Invalid epoch timestamp on line 1: "-1672531200"'
);
});
it('should throw error for epoch timestamp too far in the future', () => {
const input = '9999999999';
expect(() => convertEpochToDate(input)).toThrow(
'Invalid epoch timestamp on line 1: "9999999999"'
);
});
it('should handle multiple epoch timestamps', () => {
const input = '0\n946684800\n1577836800';
const result = convertEpochToDate(input);
const lines = result.split('\n');
expect(lines[0]).toBe('1970-01-01 00:00:00 UTC');
expect(lines[1]).toBe('2000-01-01 00:00:00 UTC');
expect(lines[2]).toBe('2020-01-01 00:00:00 UTC');
});
it('should throw error for invalid epoch on specific line', () => {
const input = '1672531200\ninvalid-epoch\n1704067199';
expect(() => convertEpochToDate(input)).toThrow(
'Invalid epoch timestamp on line 2: "invalid-epoch"'
);
});
});

View file

@ -0,0 +1,130 @@
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 { GetGroupsType } from '@components/options/ToolOptions';
import { Box } from '@mui/material';
import SimpleRadio from '@components/options/SimpleRadio';
import { convertDateToEpoch, convertEpochToDate } from './service';
import { InitialValuesType } from './types';
const initialValues: InitialValuesType = {
mode: 'dateToEpoch'
};
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'ISO 8601 Dates to Epoch',
description:
'Convert standard ISO 8601 formatted dates to epoch timestamps. This format is commonly used in APIs and data exchange.',
sampleText: `2023-01-01T00:00:00Z
2023-06-15T12:30:45Z
2023-12-31T23:59:59Z`,
sampleResult: `1672531200
1686832245
1704067199`,
sampleOptions: { mode: 'dateToEpoch' }
},
{
title: 'Common Date Formats to Epoch',
description:
'Convert various common date formats including YYYY-MM-DD, MM/DD/YYYY, and DD/MM/YYYY to epoch timestamps.',
sampleText: `2023-01-01
01/15/2023
15/06/2023
2023-12-31 18:30:00`,
sampleResult: `1672531200
1673740800
1686787200
1703961800`,
sampleOptions: { mode: 'dateToEpoch' }
},
{
title: 'Epoch to Human-Readable Dates',
description:
'Convert Unix epoch timestamps back to human-readable date format. The output format is YYYY-MM-DD HH:mm:ss UTC.',
sampleText: `1672531200
1686832245
1704067199`,
sampleResult: `2023-01-01 00:00:00 UTC
2023-06-15 12:30:45 UTC
2023-12-31 23:59:59 UTC`,
sampleOptions: { mode: 'epochToDate' }
},
{
title: 'Mixed Epoch Timestamps',
description:
'Convert multiple epoch timestamps from different years and times to readable dates.',
sampleText: `0
946684800
1577836800
1735689600`,
sampleResult: `1970-01-01 00:00:00 UTC
2000-01-01 00:00:00 UTC
2020-01-01 00:00:00 UTC
2025-01-01 00:00:00 UTC`,
sampleOptions: { mode: 'epochToDate' }
}
];
export default function ConvertDateToEpoch({
title,
longDescription
}: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: InitialValuesType, input: string) => {
if (optionsValues.mode === 'dateToEpoch') {
setResult(convertDateToEpoch(input));
} else {
setResult(convertEpochToDate(input));
}
};
const getGroups: GetGroupsType<InitialValuesType> = ({
values,
updateField
}) => [
{
title: 'Conversion Mode',
component: (
<Box>
<SimpleRadio
onClick={() => updateField('mode', 'dateToEpoch')}
checked={values.mode === 'dateToEpoch'}
title={'Date to Epoch'}
description={
'Convert human-readable dates to Unix epoch timestamps'
}
/>
<SimpleRadio
onClick={() => updateField('mode', 'epochToDate')}
checked={values.mode === 'epochToDate'}
title={'Epoch to Date'}
description={
'Convert Unix epoch timestamps to human-readable dates'
}
/>
</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,23 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('time', {
path: 'convert-date-to-epoch',
name: 'Convert Date to Epoch',
icon: 'ic:round-schedule',
description:
'Convert between dates and Unix epoch timestamps bidirectionally. This tool supports converting human-readable dates to Unix epoch timestamps (seconds since January 1, 1970 UTC) and vice versa. It handles multiple date formats including ISO 8601, MM/DD/YYYY, DD/MM/YYYY, and YYYY-MM-DD formats. Perfect for converting between human-readable dates and Unix timestamps for programming and database usage.',
shortDescription: 'Convert between dates and Unix epoch timestamps.',
keywords: [
'convert',
'epoch',
'unix',
'timestamp',
'date',
'time',
'bidirectional'
],
longDescription:
'This is a quick online utility for converting between dates and Unix epoch timestamps bidirectionally. Unix epoch time is the number of seconds that have elapsed since January 1, 1970, at 00:00:00 UTC. This tool supports two modes: Date to Epoch and Epoch to Date. In Date to Epoch mode, it converts various date formats including ISO 8601 (YYYY-MM-DDTHH:mm:ssZ), YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, and many other common formats to Unix timestamps. In Epoch to Date mode, it converts Unix epoch timestamps back to human-readable dates in YYYY-MM-DD HH:mm:ss UTC format. You can input multiple values (one per line) and the tool will convert each accordingly. The tool automatically handles timezone conversions to UTC for accurate epoch calculation and provides clear error messages for invalid inputs. This is particularly useful for developers working with databases, APIs, or any system that stores dates as Unix timestamps.',
component: lazy(() => import('./index'))
});

View file

@ -0,0 +1,131 @@
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(utc);
dayjs.extend(customParseFormat);
// Common date formats to try parsing
const DATE_FORMATS = [
'YYYY-MM-DD HH:mm:ss',
'YYYY-MM-DD HH:mm',
'YYYY-MM-DD',
'MM/DD/YYYY HH:mm:ss',
'MM/DD/YYYY HH:mm',
'MM/DD/YYYY',
'DD/MM/YYYY HH:mm:ss',
'DD/MM/YYYY HH:mm',
'DD/MM/YYYY',
'YYYY-MM-DDTHH:mm:ss.SSSZ', // ISO format
'YYYY-MM-DDTHH:mm:ssZ',
'YYYY-MM-DDTHH:mm:ss',
'ddd MMM DD YYYY HH:mm:ss' // JavaScript date string format
];
function parseDate(dateString: string): dayjs.Dayjs | null {
const trimmedInput = dateString.trim();
if (!trimmedInput) {
return null;
}
// First try to parse as a timestamp (if it's all digits)
if (/^\d+$/.test(trimmedInput)) {
const timestamp = parseInt(trimmedInput, 10);
// Check if it's a valid timestamp (reasonable range)
if (timestamp > 0 && timestamp < 4102444800) {
// Up to year 2100
return dayjs.unix(timestamp);
}
}
// Try to parse with various formats
for (const format of DATE_FORMATS) {
const parsed = dayjs(trimmedInput, format, true);
if (parsed.isValid()) {
return parsed;
}
}
// Try default dayjs parsing as fallback
const defaultParsed = dayjs(trimmedInput);
if (defaultParsed.isValid()) {
return defaultParsed;
}
return null;
}
function convertSingleDateToEpoch(
dateString: string,
lineNumber: number
): string {
if (dateString.trim() === '') {
return '';
}
const parsedDate = parseDate(dateString);
if (!parsedDate) {
throw new Error(
`Invalid date format on line ${lineNumber}: "${dateString}"`
);
}
// Convert to UTC and get Unix timestamp
return parsedDate.utc().unix().toString();
}
function convertSingleEpochToDate(
epochString: string,
lineNumber: number
): string {
if (epochString.trim() === '') {
return '';
}
const trimmedInput = epochString.trim();
// Check if it's a valid epoch timestamp (all digits)
if (!/^\d+$/.test(trimmedInput)) {
throw new Error(
`Invalid epoch timestamp on line ${lineNumber}: "${epochString}"`
);
}
const timestamp = parseInt(trimmedInput, 10);
// Check if it's a reasonable timestamp (not negative and not too far in the future)
if (timestamp < 0 || timestamp > 4102444800) {
throw new Error(
`Invalid epoch timestamp on line ${lineNumber}: "${epochString}"`
);
}
// Convert epoch to human-readable date in ISO format
return dayjs.unix(timestamp).utc().format('YYYY-MM-DD HH:mm:ss UTC');
}
export function convertDateToEpoch(input: string): string {
const result: string[] = [];
const lines = input.split('\n');
lines.forEach((line, index) => {
const epoch = convertSingleDateToEpoch(line, index + 1);
result.push(epoch);
});
return result.join('\n');
}
export function convertEpochToDate(input: string): string {
const result: string[] = [];
const lines = input.split('\n');
lines.forEach((line, index) => {
const date = convertSingleEpochToDate(line, index + 1);
result.push(date);
});
return result.join('\n');
}

View file

@ -0,0 +1,3 @@
export type InitialValuesType = {
mode: 'dateToEpoch' | 'epochToDate';
};

View file

@ -3,6 +3,7 @@ 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';
import { tool as convertDateToEpoch } from './convert-date-to-epoch/meta';
import { tool as truncateClockTime } from './truncate-clock-time/meta';
export const timeTools = [
@ -10,6 +11,7 @@ export const timeTools = [
hoursToDays,
convertSecondsToTime,
convertTimetoSeconds,
convertDateToEpoch,
truncateClockTime,
timeBetweenDates
];