tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
28
pulls
pipelines
add useLocalizedDate hook
awarm.space
4 months ago
b5e24f10
70803e89
+57
3 changed files
expand all
collapse all
unified
split
package-lock.json
package.json
src
hooks
useLocalizedDate.ts
+18
package-lock.json
···
48
48
"ioredis": "^5.6.1",
49
49
"katex": "^0.16.22",
50
50
"linkifyjs": "^4.2.0",
51
51
+
"luxon": "^3.7.2",
51
52
"multiformats": "^13.3.2",
52
53
"next": "^15.5.3",
53
54
"pg": "^8.16.3",
···
88
89
"@cloudflare/workers-types": "^4.20240512.0",
89
90
"@tailwindcss/postcss": "^4.1.13",
90
91
"@types/katex": "^0.16.7",
92
92
+
"@types/luxon": "^3.7.1",
91
93
"@types/node": "^22.15.17",
92
94
"@types/react": "19.1.3",
93
95
"@types/react-dom": "19.1.3",
···
6614
6616
"license": "MIT",
6615
6617
"peer": true
6616
6618
},
6619
6619
+
"node_modules/@types/luxon": {
6620
6620
+
"version": "3.7.1",
6621
6621
+
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.1.tgz",
6622
6622
+
"integrity": "sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg==",
6623
6623
+
"dev": true,
6624
6624
+
"license": "MIT"
6625
6625
+
},
6617
6626
"node_modules/@types/markdown-it": {
6618
6627
"version": "14.1.2",
6619
6628
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
···
12262
12271
"dev": true,
12263
12272
"dependencies": {
12264
12273
"es5-ext": "~0.10.2"
12274
12274
+
}
12275
12275
+
},
12276
12276
+
"node_modules/luxon": {
12277
12277
+
"version": "3.7.2",
12278
12278
+
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz",
12279
12279
+
"integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==",
12280
12280
+
"license": "MIT",
12281
12281
+
"engines": {
12282
12282
+
"node": ">=12"
12265
12283
}
12266
12284
},
12267
12285
"node_modules/magic-string": {
+2
package.json
···
58
58
"ioredis": "^5.6.1",
59
59
"katex": "^0.16.22",
60
60
"linkifyjs": "^4.2.0",
61
61
+
"luxon": "^3.7.2",
61
62
"multiformats": "^13.3.2",
62
63
"next": "^15.5.3",
63
64
"pg": "^8.16.3",
···
98
99
"@cloudflare/workers-types": "^4.20240512.0",
99
100
"@tailwindcss/postcss": "^4.1.13",
100
101
"@types/katex": "^0.16.7",
102
102
+
"@types/luxon": "^3.7.1",
101
103
"@types/node": "^22.15.17",
102
104
"@types/react": "19.1.3",
103
105
"@types/react-dom": "19.1.3",
+37
src/hooks/useLocalizedDate.ts
···
1
1
+
"use client";
2
2
+
import { useContext, useMemo } from "react";
3
3
+
import { DateTime } from "luxon";
4
4
+
import { RequestHeadersContext } from "components/Providers/RequestHeadersProvider";
5
5
+
6
6
+
/**
7
7
+
* Hook that formats a date string using Luxon with timezone and locale from request headers.
8
8
+
*
9
9
+
* @param dateString - ISO date string to format
10
10
+
* @param options - Intl.DateTimeFormatOptions for formatting
11
11
+
* @returns Formatted date string
12
12
+
*
13
13
+
* @example
14
14
+
* const formatted = useLocalizedDate("2024-01-15T10:30:00Z", { dateStyle: 'full', timeStyle: 'short' });
15
15
+
*/
16
16
+
export function useLocalizedDate(
17
17
+
dateString: string,
18
18
+
options?: Intl.DateTimeFormatOptions,
19
19
+
): string {
20
20
+
const { timezone, language } = useContext(RequestHeadersContext);
21
21
+
22
22
+
return useMemo(() => {
23
23
+
// Parse the date string to Luxon DateTime
24
24
+
let dateTime = DateTime.fromISO(dateString);
25
25
+
26
26
+
// Apply timezone if available
27
27
+
if (timezone) {
28
28
+
dateTime = dateTime.setZone(timezone);
29
29
+
}
30
30
+
31
31
+
// Parse locale from accept-language header (take first locale)
32
32
+
// accept-language format: "en-US,en;q=0.9,es;q=0.8"
33
33
+
const locale = language?.split(",")[0]?.split(";")[0]?.trim() || "en-US";
34
34
+
35
35
+
return dateTime.toLocaleString(options, { locale });
36
36
+
}, [dateString, options, timezone, language]);
37
37
+
}