Line data Source code
1 : import * as React from 'react';
2 :
3 : /**
4 : * Format a timestamp as relative time (e.g., "2 hours ago", "Yesterday")
5 : */
6 1 : export function formatRelativeTime(date: Date | string | null | undefined): string {
7 1 : if (!date) return 'Never';
8 :
9 1 : const timestamp = date instanceof Date ? date : new Date(date);
10 1 : const now = new Date();
11 1 : const diffMs = now.getTime() - timestamp.getTime();
12 1 : const diffSec = Math.floor(diffMs / 1000);
13 1 : const diffMin = Math.floor(diffSec / 60);
14 1 : const diffHour = Math.floor(diffMin / 60);
15 1 : const diffDay = Math.floor(diffHour / 24);
16 :
17 1 : if (diffSec < 10) {
18 1 : return 'Just now';
19 1 : } else if (diffSec < 60) {
20 1 : return `${diffSec} seconds ago`;
21 1 : } else if (diffMin === 1) {
22 1 : return '1 minute ago';
23 1 : } else if (diffMin < 60) {
24 1 : return `${diffMin} minutes ago`;
25 1 : } else if (diffHour === 1) {
26 1 : return '1 hour ago';
27 1 : } else if (diffHour < 24) {
28 1 : return `${diffHour} hours ago`;
29 1 : } else if (diffDay === 1) {
30 1 : return 'Yesterday';
31 1 : } else if (diffDay < 7) {
32 1 : return `${diffDay} days ago`;
33 1 : } else if (diffDay < 30) {
34 1 : const weeks = Math.floor(diffDay / 7);
35 1 : return weeks === 1 ? '1 week ago' : `${weeks} weeks ago`;
36 1 : } else if (diffDay < 365) {
37 1 : const months = Math.floor(diffDay / 30);
38 1 : return months === 1 ? '1 month ago' : `${months} months ago`;
39 1 : } else {
40 1 : const years = Math.floor(diffDay / 365);
41 1 : return years === 1 ? '1 year ago' : `${years} years ago`;
42 1 : }
43 1 : }
44 :
45 1 : export function useRelativeTime(timestamp: number | null, intervalMs = 15_000): string | null {
46 1 : const [label, setLabel] = React.useState<string | null>(
47 1 : () => timestamp != null ? formatRelativeTime(new Date(timestamp)) : null
48 1 : );
49 :
50 1 : React.useEffect(() => {
51 1 : if (timestamp == null) {
52 0 : setLabel(null);
53 0 : return;
54 0 : }
55 1 : setLabel(formatRelativeTime(new Date(timestamp)));
56 1 : const id = setInterval(() => setLabel(formatRelativeTime(new Date(timestamp))), intervalMs);
57 1 : return () => clearInterval(id);
58 1 : }, [timestamp, intervalMs]);
59 :
60 1 : return label;
61 1 : }
|