File size: 4,577 Bytes
5c876be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
 * Date formatting utilities for the Antaram app.
 *
 * Uses date-fns for absolute formats and a hand-rolled relative time
 * function to avoid pulling in too many locale files.
 */
import { format, isToday, isYesterday, isThisYear, parseISO } from 'date-fns';

// ─── Relative Time ───────────────────────────────────────────────────────────

/**
 * Returns a human-friendly relative time string.
 *
 * Examples:
 *   - "just now"           (< 60 seconds)
 *   - "2 min ago"          (< 60 minutes)
 *   - "1 hr ago"           (< 24 hours)
 *   - "Yesterday"          (yesterday)
 *   - "3 days ago"         (< 7 days)
 *   - "Mar 15"             (same year, >= 7 days)
 *   - "Mar 15, 2024"       (different year)
 */
export function formatRelativeTime(dateStr: string): string {
  const date = parseISO(dateStr);
  const now = new Date();
  const diffMs = now.getTime() - date.getTime();
  const diffSec = Math.floor(diffMs / 1000);
  const absDiffSec = Math.abs(diffSec);

  // Future dates (shouldn't happen often, but handle gracefully)
  if (diffSec < 0) {
    if (absDiffSec < 60) return 'in a moment';
    if (absDiffSec < 3600) {
      const mins = Math.floor(absDiffSec / 60);
      return `in ${mins} min`;
    }
    if (absDiffSec < 86400) {
      const hrs = Math.floor(absDiffSec / 3600);
      return `in ${hrs} hr${hrs > 1 ? 's' : ''}`;
    }
    return formatDate(dateStr);
  }

  // Past dates
  if (diffSec < 60) return 'just now';

  const diffMin = Math.floor(diffSec / 60);
  if (diffMin < 60) return `${diffMin} min ago`;

  const diffHr = Math.floor(diffMin / 60);
  if (diffHr < 24) return `${diffHr} hr${diffHr > 1 ? 's' : ''} ago`;

  if (isYesterday(date)) return 'Yesterday';

  const diffDays = Math.floor(diffHr / 24);
  if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;

  // Fall back to short date format
  if (isThisYear(date)) return format(date, 'MMM d');
  return format(date, 'MMM d, yyyy');
}

// ─── Absolute Date ───────────────────────────────────────────────────────────

/**
 * Format as "Mar 29, 2026"
 */
export function formatDate(dateStr: string): string {
  const date = parseISO(dateStr);
  return format(date, 'MMM d, yyyy');
}

/**
 * Format as "Mar 29, 2026 at 10:42 AM"
 */
export function formatDateTime(dateStr: string): string {
  const date = parseISO(dateStr);
  if (isThisYear(date)) {
    return format(date, 'MMM d \'at\' h:mm a');
  }
  return format(date, 'MMM d, yyyy \'at\' h:mm a');
}

// ─── Time Only ───────────────────────────────────────────────────────────────

/**
 * Format as "10:42 AM"
 */
export function formatTime(dateStr: string): string {
  const date = parseISO(dateStr);
  return format(date, 'h:mm a');
}

/**
 * Format as "10:42:03 AM" (with seconds)
 */
export function formatTimeWithSeconds(dateStr: string): string {
  const date = parseISO(dateStr);
  return format(date, 'h:mm:ss a');
}

// ─── Short Helpers ───────────────────────────────────────────────────────────

/**
 * Returns "Today", "Yesterday", or the formatted date.
 */
export function formatDayLabel(dateStr: string): string {
  const date = parseISO(dateStr);
  if (isToday(date)) return 'Today';
  if (isYesterday(date)) return 'Yesterday';
  if (isThisYear(date)) return format(date, 'EEEE, MMM d');
  return format(date, 'EEEE, MMM d, yyyy');
}

/**
 * Format as "10 Mar 2026 14:30" (for chat message timestamps)
 */
export function formatChatTimestamp(dateStr: string): string {
  const date = parseISO(dateStr);
  if (isToday(date)) return format(date, 'HH:mm');
  if (isYesterday(date)) return 'Yesterday';
  if (isThisYear(date)) return format(date, 'd MMM');
  return format(date, 'd MMM yyyy');
}

/**
 * Duration in minutes to human-readable string.
 * Example: 125 β†’ "2 hr 5 min"
 */
export function formatDuration(minutes: number): string {
  if (minutes < 1) return '< 1 min';
  const hrs = Math.floor(minutes / 60);
  const mins = Math.round(minutes % 60);
  if (hrs === 0) return `${mins} min`;
  if (mins === 0) return `${hrs} hr`;
  return `${hrs} hr ${mins} min`;
}