Add Discord timestamp tool with copy + reverse conversion

This commit is contained in:
dhaanisi
2026-02-23 21:35:36 +05:30
parent 7fa5b42adc
commit a4481dcfe9
6 changed files with 122 additions and 1 deletions
+9
View File
@@ -119,5 +119,14 @@
"description": "Convert a formatted time duration (HH:MM:SS) into a decimal hour value.",
"shortDescription": "Convert human time to decimal time",
"longDescription": "Convert a formatted time string (HH:MM:SS or HH:MM) into its decimal-hour equivalent. Hours can be any positive number, while minutes and seconds accept values from 0-59 and can be single or double digits (e.g., '12:5' or '12:05'). This function interprets hours, minutes, and seconds, then calculates the total duration as a single decimal value. It is useful for productivity tracking, payroll calculations, time-based billing, data analysis, or any workflow that requires converting human-readable time into a numerical format that can be easily summed, compared, or processed. For example, '03:26:00' becomes 3.43 hours, and '12:5' becomes 12.08 hours."
},
"discordTimestamp": {
"name": "Discord Timestamp Generator",
"description": "Generate Discord formatted timestamps from date and time",
"shortDescription": "Generate Discord timestamps",
"toolInfo": {
"title": "What is a Discord Timestamp",
"description": "Discord timestamps allow you to display dynamic dates and times that automatically adjust to each user's local timezone. This tool converts a date and time into the special Discord timestamp format."
}
}
}
@@ -0,0 +1,72 @@
import { useState } from 'react';
function convertInput(input: string) {
const trimmed = input.trim();
// Case 1: Discord timestamp → normal date
const match = trimmed.match(/^<t:(\d+):[A-Za-z]>$/);
if (match) {
const unix = Number(match[1]);
const date = new Date(unix * 1000);
if (!isNaN(date.getTime())) {
return date.toISOString().replace('T', ' ').slice(0, 16);
}
}
// Case 2: normal date → Discord timestamp
const date = new Date(trimmed);
if (isNaN(date.getTime())) return 'Invalid date/time';
const unix = Math.floor(date.getTime() / 1000);
return `<t:${unix}:F>`;
}
export default function DiscordTimestamp() {
const [value, setValue] = useState('');
const [copied, setCopied] = useState(false);
const result = value ? convertInput(value) : '';
const handleCopy = async () => {
if (!result || result === 'Invalid date/time') return;
try {
await navigator.clipboard.writeText(result);
setCopied(true);
setTimeout(() => setCopied(false), 1200);
} catch (e) {
console.error('Copy failed', e);
}
};
return (
<div className="flex gap-3 items-stretch">
<textarea
placeholder="Enter date like: 2026-02-23 18:30"
value={value}
onChange={(e) => setValue(e.target.value)}
className="flex-1 min-h-[140px] p-3 rounded-lg bg-neutral-900 text-white border border-neutral-700 placeholder-neutral-400 focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<div className="flex-1 relative flex">
<textarea
readOnly
value={value ? result : 'Enter a date to generate timestamp'}
className="flex-1 w-full min-h-[140px] p-3 pr-12 pt-10 rounded-lg bg-neutral-900 text-white border border-neutral-700 focus:outline-none"
/>
<button
onClick={handleCopy}
disabled={!result || result === 'Invalid date/time'}
className="absolute top-2 right-2 w-8 h-8 flex items-center justify-center rounded-md bg-neutral-800 border border-neutral-700 hover:bg-neutral-700 text-neutral-200 disabled:opacity-40"
title="Copy to clipboard"
>
{copied ? '✓' : '📋'}
</button>
{copied && (
<span className="absolute top-3 right-12 text-xs text-green-400">
Copied
</span>
)}
</div>
</div>
);
}
@@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
const DiscordTimestamp = lazy(() => import('./index'));
export const tool = defineTool('time', {
path: 'discord-timestamp',
component: DiscordTimestamp,
icon: 'mdi:clock',
keywords: ['discord', 'timestamp', 'time'],
i18n: {
name: 'time:discordTimestamp.name',
description: 'time:discordTimestamp.description',
shortDescription: 'time:discordTimestamp.shortDescription'
}
});
@@ -0,0 +1,16 @@
// Converts a Date object to a Discord timestamp string
export function generateDiscordTimestamp(date: Date, format: string = 'F') {
const unix = Math.floor(date.getTime() / 1000);
return `<t:${unix}:${format}>`;
}
// Attempts to parse a Discord timestamp like <t:1712345678:F>
// Returns a Date object or null if invalid
export function parseDiscordTimestamp(input: string): Date | null {
const match = input.trim().match(/^<t:(\d+):[A-Za-z]>$/);
if (!match) return null;
const unix = Number(match[1]);
const date = new Date(unix * 1000);
return isNaN(date.getTime()) ? null : date;
}
@@ -0,0 +1,7 @@
export interface DiscordTimestampInput {
date: string;
}
export interface DiscordTimestampResult {
value: string;
}
+3 -1
View File
@@ -8,6 +8,7 @@ import { tool as convertSecondsToTime } from './convert-seconds-to-time/meta';
import { tool as convertTimetoSeconds } from './convert-time-to-seconds/meta';
import { tool as truncateClockTime } from './truncate-clock-time/meta';
import { tool as checkLeapYear } from './check-leap-years/meta';
import { tool as discordTimestamp } from './discord-timestamp/meta';
export const timeTools = [
daysDoHours,
@@ -19,5 +20,6 @@ export const timeTools = [
timeCrontabGuru,
checkLeapYear,
timeConvertUnixToDate,
timeConvertTimeToDecimal
timeConvertTimeToDecimal,
discordTimestamp
];