package com.bitcointxoko.gudariwallet.util import timber.log.Timber import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.format.FormatStyle // ── Epoch formatters ────────────────────────────────────────────────────────── // // All formatters are built on each call so that ZoneId.systemDefault() and the // current locale are always fresh (a file-level val would capture them once at // class-load time and become stale after a timezone/locale change). /** * "dd MMM" — e.g. "09 Jun" * Suitable for compact list labels. */ fun formatEpochShort(epochSeconds: Long): String = DateTimeFormatter.ofPattern("dd MMM") .withZone(ZoneId.systemDefault()) .format(Instant.ofEpochSecond(epochSeconds)) /** * "dd MMM yyyy, HH:mm" — e.g. "09 Jun 2025, 14:32" * Accepts either a numeric epoch-seconds value or an ISO offset-date-time string * as [rawTime] fallback (for payments not yet persisted through Room). */ fun formatTimestamp(createdAt: Long?, rawTime: String): String { val formatter = DateTimeFormatter .ofPattern("dd MMM yyyy, HH:mm") .withZone(ZoneId.systemDefault()) if (createdAt != null && createdAt > 1_000_000_000L) { return formatter.format(Instant.ofEpochSecond(createdAt)) } return runCatching { formatter.format(Instant.ofEpochSecond(rawTime.toLong())) }.recoverCatching { formatter.format(java.time.OffsetDateTime.parse(rawTime)) }.getOrDefault(rawTime) } /** * Localized SHORT date-time — e.g. "6/9/25, 2:32 PM" (locale-dependent). * Returns "—" for out-of-range epoch values; callers should handle sentinel * values (e.g. 0L = "never expires") before calling this. */ fun formatEpoch(epochSeconds: Long): String = try { DateTimeFormatter .ofLocalizedDateTime(FormatStyle.SHORT) .withZone(ZoneId.systemDefault()) .format(Instant.ofEpochSecond(epochSeconds)) } catch (e: Exception) { Timber.tag("DateTimeUtils").w(e, "formatEpoch: could not format epochSeconds=$epochSeconds") "—" }