Skip to content

Timestamp Converter — Kotlin source

Convert Unix epoch timestamps to human-readable dates and back. See seconds, milliseconds, ISO 8601, UTC, local and relative time at once.

This is the Kotlin implementation — the same logic the interactive tool runs, in a shareable, citable form.

// timestamp — Unix epoch (seconds & milliseconds) <-> ISO 8601 / UTC / local strings and relative time ("3 hr ago" / "in 2 day"). Kotlin (1.9+) port of src/tools/TimestampConverter.tsx — same logic as this dir's typescript.ts; fromISO parsing omitted for the 80-line budget (see typescript.ts / python.py).
import java.time.Instant
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.util.Locale
import kotlin.math.abs
import kotlin.math.roundToLong

// Fixed formatters: ISO with milliseconds ("...T07:00:00.000Z") and the
// toUTCString() shape ("Wed, 14 Jun 2017 07:00:00 GMT"), English names.
private val ISO =
    DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH).withZone(ZoneOffset.UTC)
private val UTC =
    DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH).withZone(ZoneOffset.UTC)
private val LOCAL = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")

// Human relative time: bucket |now - t| into sec/min/hr/day/month/yr with
// the island's 60s / 60m / 24h / 30d / 365d thresholds, round to the
// nearest whole unit, then sign it ("ago" past / "in" future).
fun relativeTime(ms: Long, nowMs: Long): String {
    val diff = ms - nowMs
    val a = abs(diff.toDouble()) / 1000.0
    val (n, unit) = when {
        a < 60 -> a.roundToLong() to "sec"
        a < 3_600 -> (a / 60).roundToLong() to "min"
        a < 86_400 -> (a / 3_600).roundToLong() to "hr"
        a < 86_400 * 30 -> (a / 86_400).roundToLong() to "day"
        a < 86_400 * 365 -> (a / (86_400 * 30)).roundToLong() to "month"
        else -> (a / (86_400 * 365)).roundToLong() to "yr"
    }
    return if (diff < 0) "$n $unit ago" else "in $n $unit"
}

// Render every form the tool exposes from "now" — the island's row table:
// epoch (s), epoch (ms), ISO 8601, UTC string, local string, relative time.
fun main() {
    val now = Instant.now()
    val ms = now.toEpochMilli()
    println("Epoch (s):  ${ms / 1000}")
    println("Epoch (ms): $ms")
    println("ISO 8601:  ${ISO.format(now)}")
    println("UTC:       ${UTC.format(now)}")
    println("Local:     ${LOCAL.format(now.atZone(ZoneId.systemDefault()))}")
    println("Relative:  ${relativeTime(ms, ms)}")
    println("In 3 hr:   ${relativeTime(ms + 3 * 3_600_000, ms)}")
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →