discord-timestamp-kit 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/discordTimestamp.d.ts +1 -1
- package/dist/index.js +27 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,8 @@ for (const f of DISCORD_FORMATS) {
|
|
|
26
26
|
// D Long Date <t:1798765200:D>
|
|
27
27
|
// f Short Date/Time <t:1798765200:f>
|
|
28
28
|
// F Long Date/Time <t:1798765200:F>
|
|
29
|
+
// s Short Date + Time <t:1798765200:s>
|
|
30
|
+
// S Short Date + Long Time <t:1798765200:S>
|
|
29
31
|
// R Relative Time <t:1798765200:R>
|
|
30
32
|
```
|
|
31
33
|
|
|
@@ -61,6 +63,7 @@ import { decodeSnowflake } from 'discord-timestamp-kit';
|
|
|
61
63
|
const s = decodeSnowflake('175928847299117063');
|
|
62
64
|
// { unixMs: 1462015105796, unixSeconds: 1462015105, workerId: 1, processId: 0, increment: 7 }
|
|
63
65
|
new Date(s!.unixMs).toISOString(); // '2016-04-30T11:18:25.796Z'
|
|
66
|
+
decodeSnowflake('https://discord.com/channels/81384788765712384/81384788765712384/175928847299117063'); // same result: message links work too
|
|
64
67
|
```
|
|
65
68
|
|
|
66
69
|
Message, user, channel and server IDs are all snowflakes. The bit math uses BigInt, so IDs above `Number.MAX_SAFE_INTEGER` decode exactly. Pass the ID as a string.
|
|
@@ -70,7 +73,7 @@ Message, user, channel and server IDs are all snowflakes. The bit math uses BigI
|
|
|
70
73
|
```ts
|
|
71
74
|
import { renderDiscordPreview } from 'discord-timestamp-kit';
|
|
72
75
|
|
|
73
|
-
renderDiscordPreview(1798765200, 'F'); // e.g. 'Thursday, December 31, 2026 8:00 PM'
|
|
76
|
+
renderDiscordPreview(1798765200, 'F'); // e.g. 'Thursday, December 31, 2026 at 8:00 PM'
|
|
74
77
|
renderDiscordPreview(1798765200, 'R', 1798758000); // 'in 2 hours'
|
|
75
78
|
```
|
|
76
79
|
|
|
@@ -80,7 +83,7 @@ The preview uses Discord's en-US layout, in the runtime's local time zone. The `
|
|
|
80
83
|
|
|
81
84
|
| Export | What it does |
|
|
82
85
|
|---|---|
|
|
83
|
-
| `DISCORD_FORMATS` | The
|
|
86
|
+
| `DISCORD_FORMATS` | The 9 format codes (`t T d D f F s S R`, in Discord's documented order) with label, description and example |
|
|
84
87
|
| `buildTimestampCode(unix, code)` | Returns `<t:unix:code>` |
|
|
85
88
|
| `dateTimeToUnixInTz(date, time, timeZone?)` | Converts a wall-clock date and time in an IANA zone to Unix seconds, DST-safe |
|
|
86
89
|
| `parseUnixInput(raw)` | Parses an integer string in seconds or milliseconds, or returns `null` |
|
package/dist/index.js
CHANGED
|
@@ -8,13 +8,25 @@ var DISCORD_FORMATS = [
|
|
|
8
8
|
code: "f",
|
|
9
9
|
label: "Short Date/Time",
|
|
10
10
|
description: "Discord's default when you paste a timestamp",
|
|
11
|
-
example: "November 28, 2018 9:01 PM"
|
|
11
|
+
example: "November 28, 2018 at 9:01 PM"
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
code: "F",
|
|
15
15
|
label: "Long Date/Time",
|
|
16
16
|
description: "Includes the day of the week",
|
|
17
|
-
example: "Wednesday, November 28, 2018 9:01 PM"
|
|
17
|
+
example: "Wednesday, November 28, 2018 at 9:01 PM"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
code: "s",
|
|
21
|
+
label: "Short Date + Time",
|
|
22
|
+
description: "Numeric date with hours and minutes",
|
|
23
|
+
example: "11/28/2018, 9:01 PM"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
code: "S",
|
|
27
|
+
label: "Short Date + Long Time",
|
|
28
|
+
description: "Numeric date with seconds",
|
|
29
|
+
example: "11/28/2018, 9:01:00 PM"
|
|
18
30
|
},
|
|
19
31
|
{
|
|
20
32
|
code: "R",
|
|
@@ -37,7 +49,8 @@ function parseUnixInput(raw) {
|
|
|
37
49
|
}
|
|
38
50
|
var DISCORD_EPOCH_MS = 1420070400000n;
|
|
39
51
|
function decodeSnowflake(raw) {
|
|
40
|
-
const
|
|
52
|
+
const link = /^https?:\/\/(?:(?:ptb|canary)\.)?discord(?:app)?\.com\/channels\/(?:@me|\d+)\/\d+(?:\/(\d+))?\/?$/.exec(raw.trim());
|
|
53
|
+
const trimmed = link ? link[1] ?? raw.trim().split("/").filter(Boolean).pop() : raw.trim();
|
|
41
54
|
if (!/^\d{1,20}$/.test(trimmed)) return null;
|
|
42
55
|
let id;
|
|
43
56
|
try {
|
|
@@ -75,6 +88,9 @@ var MONTH_NAMES = [
|
|
|
75
88
|
function pad(n) {
|
|
76
89
|
return n.toString().padStart(2, "0");
|
|
77
90
|
}
|
|
91
|
+
function shortDate(d) {
|
|
92
|
+
return `${pad(d.getMonth() + 1)}/${pad(d.getDate())}/${d.getFullYear()}`;
|
|
93
|
+
}
|
|
78
94
|
function formatTime(d, withSeconds) {
|
|
79
95
|
let hours = d.getHours();
|
|
80
96
|
const minutes = pad(d.getMinutes());
|
|
@@ -115,13 +131,17 @@ function renderDiscordPreview(unixSeconds, code, nowSeconds = Math.floor(Date.no
|
|
|
115
131
|
case "T":
|
|
116
132
|
return formatTime(d, true);
|
|
117
133
|
case "d":
|
|
118
|
-
return
|
|
134
|
+
return shortDate(d);
|
|
119
135
|
case "D":
|
|
120
136
|
return `${MONTH_NAMES[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`;
|
|
121
137
|
case "f":
|
|
122
|
-
return `${MONTH_NAMES[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()} ${formatTime(d, false)}`;
|
|
138
|
+
return `${MONTH_NAMES[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()} at ${formatTime(d, false)}`;
|
|
123
139
|
case "F":
|
|
124
|
-
return `${DAY_NAMES[d.getDay()]}, ${MONTH_NAMES[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()} ${formatTime(d, false)}`;
|
|
140
|
+
return `${DAY_NAMES[d.getDay()]}, ${MONTH_NAMES[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()} at ${formatTime(d, false)}`;
|
|
141
|
+
case "s":
|
|
142
|
+
return `${shortDate(d)}, ${formatTime(d, false)}`;
|
|
143
|
+
case "S":
|
|
144
|
+
return `${shortDate(d)}, ${formatTime(d, true)}`;
|
|
125
145
|
case "R":
|
|
126
146
|
return formatRelative(unixSeconds, nowSeconds);
|
|
127
147
|
default:
|
|
@@ -172,6 +192,7 @@ function dateTimeToUnixInTz(dateValue, timeValue, timeZone) {
|
|
|
172
192
|
let actualUtc = utcGuess - offset1;
|
|
173
193
|
const offset2 = offsetAt(actualUtc);
|
|
174
194
|
if (offset2 !== offset1) actualUtc = utcGuess - offset2;
|
|
195
|
+
if (offsetAt(actualUtc) !== offset2) actualUtc = utcGuess - Math.min(offset1, offset2);
|
|
175
196
|
return Math.floor(actualUtc / 1e3);
|
|
176
197
|
} catch {
|
|
177
198
|
const date = new Date(y, m - 1, d, h, min, 0, 0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "discord-timestamp-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Make Discord <t:unix:F> timestamp codes, convert a local date and time in any IANA time zone to Unix (DST-safe), parse seconds or milliseconds, and decode Discord snowflake IDs. Zero dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|