export interface FormatUnixTimestampResult { time: string; timezone: string; } export const formatUnixTimestamp = ( timestamp: number, locale?: string | string[], options?: Intl.DateTimeFormatOptions ): FormatUnixTimestampResult => { const milliseconds = timestamp * 1000; const date = new Date(milliseconds); const formattedTime = date.toLocaleString(locale, options); // Calculate UTC offset in hours // getTimezoneOffset() returns offset in minutes (negative if ahead of UTC) const offsetMinutes = date.getTimezoneOffset(); const offsetHours = -offsetMinutes / 60; const offsetSign = offsetHours >= 0 ? '+' : '-'; const offsetAbs = Math.abs(offsetHours); // Format as UTC +2 or UTC -5 (with space and sign) let timezone: string; if (options?.timeZone) { // If a specific timezone is requested, calculate offset for that timezone try { // Get the offset for the specified timezone const formatter = new Intl.DateTimeFormat('en', { timeZone: options.timeZone, timeZoneName: 'shortOffset' }); const parts = formatter.formatToParts(date); const offsetPart = parts.find(part => part.type === 'timeZoneName'); if (offsetPart?.value) { // Format like "GMT+2" or "GMT-5" timezone = offsetPart.value.replace('GMT', 'UTC'); } else { // Fallback: calculate offset manually const utcTime = date.getTime() + (date.getTimezoneOffset() * 60000); const tzDate = new Date(utcTime); const tzFormatter = new Intl.DateTimeFormat('en', { timeZone: options.timeZone, hour: '2-digit', hour12: false }); const utcFormatter = new Intl.DateTimeFormat('en', { timeZone: 'UTC', hour: '2-digit', hour12: false }); const tzHour = parseInt(tzFormatter.format(tzDate)); const utcHour = parseInt(utcFormatter.format(tzDate)); const tzOffset = tzHour - utcHour; const tzSign = tzOffset >= 0 ? '+' : '-'; const tzAbs = Math.abs(tzOffset); timezone = `UTC ${tzSign}${tzAbs}`; } } catch { // Fallback to browser timezone timezone = `UTC ${offsetSign}${offsetAbs}`; } } else { // Use browser's timezone offset timezone = `UTC ${offsetSign}${offsetAbs}`; } return { time: formattedTime, timezone, }; };