( timestamp: string, style: 'long' | 'short' = 'long', )
| 191 | * @param style - 'long' (e.g. "2 hours ago") or 'short' (e.g. "2h") |
| 192 | */ |
| 193 | export const formatRelativeTime = ( |
| 194 | timestamp: string, |
| 195 | style: 'long' | 'short' = 'long', |
| 196 | ): string => { |
| 197 | const now = new Date(); |
| 198 | const time = new Date(timestamp); |
| 199 | const diffMs = now.getTime() - time.getTime(); |
| 200 | const diffSeconds = Math.floor(diffMs / 1000); |
| 201 | const diffMinutes = Math.floor(diffSeconds / 60); |
| 202 | const diffHours = Math.floor(diffMinutes / 60); |
| 203 | const diffDays = Math.floor(diffHours / 24); |
| 204 | |
| 205 | if (style === 'short') { |
| 206 | if (diffSeconds < 1) return 'now'; |
| 207 | if (diffSeconds < 60) return `${diffSeconds}s`; |
| 208 | if (diffMinutes < 60) return `${diffMinutes}m`; |
| 209 | if (diffHours < 24) return `${diffHours}h`; |
| 210 | if (diffDays < 30) return `${diffDays}d`; |
| 211 | const diffMonths = Math.floor(diffDays / 30); |
| 212 | return diffMonths < 12 |
| 213 | ? `${diffMonths}mo` |
| 214 | : `${Math.floor(diffMonths / 12)}y`; |
| 215 | } else { |
| 216 | if (diffDays > 0) { |
| 217 | return `${diffDays} day${diffDays === 1 ? '' : 's'} ago`; |
| 218 | } else if (diffHours > 0) { |
| 219 | return `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`; |
| 220 | } else if (diffMinutes > 0) { |
| 221 | return `${diffMinutes} minute${diffMinutes === 1 ? '' : 's'} ago`; |
| 222 | } else { |
| 223 | return 'Just now'; |
| 224 | } |
| 225 | } |
| 226 | }; |
| 227 | |
| 228 | export interface GetSessionOptions { |
| 229 | /** Whether to load full message content (needed for search) */ |
no outgoing calls
no test coverage detected