(** Formatting Git dates for display. Git records a commit date as a Unix timestamp plus the offset of the zone the author was in. Relative and short forms drop that offset and use the server's local zone, which is what a reader scanning a list wants; the detailed form preserves it, because on a single commit the author's own wall-clock time is the meaningful one. *) let relative_time (date, _) = let seconds = Unix.time () -. Int64.to_float date |> int_of_float in let minutes = seconds / 60 in let hours = minutes / 60 in let days = hours / 24 in let months = days / 30 in let years = months / 12 in let quantity value singular = Printf.sprintf "%d %s%s ago" value singular (if value = 1 then "" else "s") in match seconds with | s when s < 60 -> "just now" | _ when minutes < 60 -> quantity minutes "minute" | _ when hours < 24 -> quantity hours "hour" | _ when days < 30 -> quantity days "day" | _ when months < 12 -> quantity months "month" | _ -> quantity years "year" (** Minute precision, server-local, for dense listings. *) let short_time (date, _) = let tm = date |> Int64.to_float |> Unix.localtime in Printf.sprintf "%04d-%02d-%02d %02d:%02d" (tm.tm_year + 1900) (tm.tm_mon + 1) tm.tm_mday tm.tm_hour tm.tm_min (** Second precision in the recorded zone. Returns the machine-readable form for a [datetime] attribute alongside the human-readable form. *) let exact_time (date, timezone) = let offset_seconds, suffix = match timezone with | None -> (0, "Z") | Some (offset : Git.User.tz_offset) -> let direction = match offset.sign with `Plus -> 1 | `Minus -> -1 in let seconds = direction * ((offset.hours * 60) + offset.minutes) * 60 in let sign = match offset.sign with `Plus -> "+" | `Minus -> "-" in (seconds, Printf.sprintf "%s%02d:%02d" sign offset.hours offset.minutes) in let adjusted = Int64.add date (Int64.of_int offset_seconds) in let tm = adjusted |> Int64.to_float |> Unix.gmtime in let day = Printf.sprintf "%04d-%02d-%02d" (tm.tm_year + 1900) (tm.tm_mon + 1) tm.tm_mday in let clock = Printf.sprintf "%02d:%02d:%02d" tm.tm_hour tm.tm_min tm.tm_sec in ( Printf.sprintf "%sT%s%s" day clock suffix, Printf.sprintf "%s %s %s" day clock suffix )