|
1 | 1 | "use client"; |
2 | 2 |
|
3 | | -import { CopyTextButton } from "@/components/ui/CopyTextButton"; |
| 3 | +import {} from "@/components/ui/alert"; |
| 4 | +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; |
4 | 5 | import { Input } from "@/components/ui/input"; |
5 | 6 | import { Label } from "@/components/ui/label"; |
6 | | -import { formatDistanceToNow } from "date-fns"; |
7 | | -import { useState } from "react"; |
8 | | -import { ShareButton } from "../../components/share"; |
9 | | - |
10 | | -export const UnixTimeConverter = () => { |
11 | | - const getCurrentUnixMilliseconds = () => Math.floor(new Date().getTime()); |
12 | | - const [unix, setUnix] = useState<number>(getCurrentUnixMilliseconds()); |
13 | | - |
14 | | - // `unix` may be in milliseconds or seconds. |
15 | | - // Treat any value < 100000000000 as seconds, otherwise milliseconds. |
16 | | - const isSeconds = unix < 100000000000; |
17 | | - const date = new Date(isSeconds ? unix * 1000 : unix); |
18 | | - const dateLocal = date.toLocaleString(undefined, { |
19 | | - timeZoneName: "short", |
20 | | - }); |
21 | | - const dateUTC = date.toLocaleString(undefined, { |
22 | | - timeZoneName: "short", |
23 | | - timeZone: "UTC", |
| 7 | +import { |
| 8 | + formatDistanceToNow, |
| 9 | + formatISO9075, |
| 10 | + formatRFC3339, |
| 11 | + formatRFC7231, |
| 12 | + fromUnixTime, |
| 13 | +} from "date-fns"; |
| 14 | +import { useMemo, useState } from "react"; |
| 15 | + |
| 16 | +export function UnixTimeConverter() { |
| 17 | + const [unixTime, setUnixTime] = useState(() => { |
| 18 | + return Math.floor(Date.now() / 1000); |
24 | 19 | }); |
25 | 20 |
|
| 21 | + const { date, error } = useMemo(() => { |
| 22 | + if (Number.isNaN(unixTime) || !Number.isInteger(unixTime)) { |
| 23 | + return { |
| 24 | + error: "Invalid Unix Timestamp", |
| 25 | + date: null, |
| 26 | + }; |
| 27 | + } |
| 28 | + |
| 29 | + const date = fromUnixTime(unixTime); |
| 30 | + |
| 31 | + if (!isValidDate(date)) { |
| 32 | + return { |
| 33 | + date: null, |
| 34 | + error: "Invalid Unix Timestamp", |
| 35 | + }; |
| 36 | + } |
| 37 | + |
| 38 | + return { |
| 39 | + date, |
| 40 | + error: null, |
| 41 | + }; |
| 42 | + }, [unixTime]); |
| 43 | + |
26 | 44 | return ( |
27 | | - <div className="space-y-24"> |
28 | | - <div className="space-y-4"> |
29 | | - <div className="flex flex-col gap-2 sm:flex-row sm:items-center"> |
30 | | - <Label htmlFor="unix-input" className="min-w-64 text-xl"> |
31 | | - Unix Time |
32 | | - </Label> |
33 | | - <Input |
34 | | - id="unix-input" |
35 | | - type="number" |
36 | | - value={unix} |
37 | | - onChange={(e) => { |
38 | | - if (!Number.isNaN(e.target.valueAsNumber)) { |
39 | | - setUnix(e.target.valueAsNumber); |
40 | | - } |
41 | | - }} |
42 | | - placeholder="Enter a Unix time in milliseconds or seconds" |
43 | | - className="p-6 text-xl" |
44 | | - /> |
45 | | - </div> |
46 | | - <div className="flex flex-col gap-2 sm:flex-row sm:items-center"> |
47 | | - <Label className="min-w-64 text-xl">Time (local)</Label> |
48 | | - <div> |
49 | | - <CopyTextButton |
50 | | - textToCopy={dateLocal} |
51 | | - textToShow={dateLocal} |
52 | | - tooltip="Copy" |
53 | | - copyIconPosition="right" |
54 | | - className="font-mono text-xl" |
| 45 | + <div className="mx-auto max-w-2xl"> |
| 46 | + <Card> |
| 47 | + <CardHeader className="mb-6 border-b"> |
| 48 | + <CardTitle className="font-bold text-2xl"> |
| 49 | + Unix Time Converter |
| 50 | + </CardTitle> |
| 51 | + </CardHeader> |
| 52 | + |
| 53 | + <CardContent> |
| 54 | + <div className="mb-4"> |
| 55 | + <Label htmlFor="unixTime">Enter Unix Timestamp</Label> |
| 56 | + <Input |
| 57 | + id="unixTime" |
| 58 | + type="number" |
| 59 | + value={unixTime} |
| 60 | + onChange={(e) => { |
| 61 | + setUnixTime(Number(e.target.value)); |
| 62 | + }} |
| 63 | + placeholder="e.g., 1609459200" |
| 64 | + className="mt-1" |
55 | 65 | /> |
| 66 | + {error && ( |
| 67 | + <p className="mt-2 text-destructive-text text-sm">{error}</p> |
| 68 | + )} |
56 | 69 | </div> |
57 | | - <p className="text-sm italic"> |
58 | | - ← {formatDistanceToNow(date, { addSuffix: true })} |
59 | | - </p> |
60 | | - </div> |
61 | | - <div className="flex flex-col gap-2 sm:flex-row sm:items-center"> |
62 | | - <Label className="min-w-64 text-xl">Time (UTC)</Label> |
63 | | - <div> |
64 | | - <CopyTextButton |
65 | | - textToCopy={dateUTC} |
66 | | - textToShow={dateUTC} |
67 | | - tooltip="Copy" |
68 | | - copyIconPosition="right" |
69 | | - className="font-mono text-xl" |
70 | | - /> |
| 70 | + |
| 71 | + <div className="flex flex-col gap-4"> |
| 72 | + <div> |
| 73 | + <Label>Relative Time</Label> |
| 74 | + <p className="font-mono text-muted-foreground"> |
| 75 | + {date |
| 76 | + ? formatDistanceToNow(date, { |
| 77 | + addSuffix: true, |
| 78 | + }) |
| 79 | + : "---"} |
| 80 | + </p> |
| 81 | + </div> |
| 82 | + <div> |
| 83 | + <Label>Local Time</Label> |
| 84 | + <p className="font-mono text-muted-foreground"> |
| 85 | + {date ? formatLocal(date) : "---"} |
| 86 | + </p> |
| 87 | + </div> |
| 88 | + <div> |
| 89 | + <Label>UTC Time</Label> |
| 90 | + <p className="font-mono text-muted-foreground"> |
| 91 | + {date ? formatUTC(date) : "---"} |
| 92 | + </p> |
| 93 | + </div> |
| 94 | + |
| 95 | + <div> |
| 96 | + <Label>ISO 8601</Label> |
| 97 | + <p className="font-mono text-muted-foreground"> |
| 98 | + {date ? formatISO8601(date) : "---"} |
| 99 | + </p> |
| 100 | + </div> |
| 101 | + |
| 102 | + <div> |
| 103 | + <Label>ISO 9075</Label> |
| 104 | + <p className="font-mono text-muted-foreground"> |
| 105 | + {date ? formatISO9075(date) : "---"} |
| 106 | + </p> |
| 107 | + </div> |
| 108 | + <div> |
| 109 | + <Label>RFC 7231</Label> |
| 110 | + <p className="font-mono text-muted-foreground"> |
| 111 | + {date ? formatRFC7231(date) : "---"} |
| 112 | + </p> |
| 113 | + </div> |
| 114 | + <div> |
| 115 | + <Label>RFC 3339</Label> |
| 116 | + <p className="font-mono text-muted-foreground"> |
| 117 | + {date ? formatRFC3339(date) : "---"} |
| 118 | + </p> |
| 119 | + </div> |
| 120 | + <div> |
| 121 | + <Label>SQL Timestamp</Label> |
| 122 | + <p className="font-mono text-muted-foreground"> |
| 123 | + {date ? formatSQL(date) : "---"} |
| 124 | + </p> |
| 125 | + </div> |
71 | 126 | </div> |
72 | | - </div> |
73 | | - <div className="mt-4 flex justify-end"> |
74 | | - <ShareButton |
75 | | - cta="Share on X" |
76 | | - href="https://twitter.com/intent/tweet?text=Easy-to-use%20Unix%20time%20converter%20by%20thirdweb%20%F0%9F%98%8D&url=https%3A%2F%2Fthirdweb.com%2Ftools%2Funixtime-converter" |
77 | | - /> |
78 | | - </div> |
79 | | - </div> |
80 | | - |
81 | | - <div className="space-y-4"> |
82 | | - <h1 className="font-bold text-2xl"> |
83 | | - Convert Unix time in milliseconds or seconds |
84 | | - </h1> |
85 | | - |
86 | | - <p> |
87 | | - Timestamps are often represented in Unix time for several key reasons: |
88 | | - </p> |
89 | | - <h2 className="font-bold text-md">Simplicity</h2> |
90 | | - <p> |
91 | | - Counts seconds since January 1, 1970, making it easy to understand and |
92 | | - manipulate. |
93 | | - </p> |
94 | | - <h2 className="font-bold text-md">Consistency</h2> |
95 | | - <p> |
96 | | - Provides a uniform time representation across systems, unaffected by |
97 | | - time zones or calendar changes. |
98 | | - </p> |
99 | | - <h2 className="font-bold text-md">Standardization</h2> |
100 | | - <p> |
101 | | - Widely supported in computing, ensuring compatibility across |
102 | | - platforms. |
103 | | - </p> |
104 | | - <h2 className="font-bold text-md">Calculation</h2> |
105 | | - <p> |
106 | | - Allows straightforward arithmetic operations for time differences. |
107 | | - </p> |
108 | | - <h2 className="font-bold text-md">Efficiency</h2> |
109 | | - <p> |
110 | | - Stores time as a single integer, conserving memory and computational |
111 | | - resources. |
112 | | - </p> |
113 | | - <h2 className="font-bold text-md">Interoperability</h2> |
114 | | - <p>Facilitates seamless data exchange between systems and languages.</p> |
115 | | - </div> |
| 127 | + </CardContent> |
| 128 | + </Card> |
116 | 129 | </div> |
117 | 130 | ); |
118 | | -}; |
| 131 | +} |
| 132 | + |
| 133 | +function formatLocal(date: Date): string { |
| 134 | + return date.toLocaleString(); |
| 135 | +} |
| 136 | + |
| 137 | +function formatUTC(date: Date): string { |
| 138 | + return date.toUTCString(); |
| 139 | +} |
| 140 | + |
| 141 | +function isValidDate(date: Date): boolean { |
| 142 | + return !Number.isNaN(date.getTime()); |
| 143 | +} |
| 144 | + |
| 145 | +function formatISO8601(date: Date): string { |
| 146 | + return date.toISOString(); |
| 147 | +} |
| 148 | + |
| 149 | +function formatSQL(date: Date): string { |
| 150 | + return date.toISOString().slice(0, 19).replace("T", " "); |
| 151 | +} |
0 commit comments