mte/unikernel/duniverse/duration/duration.ml

160 lines
3.7 KiB
OCaml
Raw Normal View History

2025-11-11 02:07:51 +01:00
type t = int64
let of_us_64 m =
if m < 0L then
invalid_arg "negative" ;
if Int64.compare m 0x4189374BC6A7EDL = 1 then
invalid_arg "out of range" ;
Int64.mul 1_000L m
let of_us m = of_us_64 (Int64.of_int m)
let of_ms_64 m =
if m < 0L then
invalid_arg "negative" ;
if Int64.compare m 0x10C6F7A0B5EDL = 1 then
invalid_arg "out of range" ;
Int64.mul 1_000_000L m
let of_ms m = of_ms_64 (Int64.of_int m)
let of_sec_64 s =
if s < 0L then
invalid_arg "negative" ;
if Int64.compare s 0x44B82FA09L = 1 then
invalid_arg "out of range" ;
Int64.mul 1_000_000_000L s
let of_sec m = of_sec_64 (Int64.of_int m)
let of_min m =
if m < 0 then
invalid_arg "negative" ;
let m = Int64.of_int m in
if Int64.compare m 0x12533FE6L = 1 then
invalid_arg "out of range" ;
Int64.mul 60_000_000_000L m
let hour = 3600_000_000_000L
let of_hour h =
if h < 0 then
invalid_arg "negative" ;
let h = Int64.of_int h in
if Int64.compare h 0x4E2FFFL = 1 then
invalid_arg "out of range" ;
Int64.mul hour h
let day = Int64.mul 24L hour
let of_day d =
if d < 0 then
invalid_arg "negative" ;
let d = Int64.of_int d in
if Int64.compare d 0x341FFL = 1 then
invalid_arg "out of range" ;
Int64.mul day d
let year = Int64.mul 8766L hour
let of_year y =
if y < 0 then
invalid_arg "negative" ;
let y = Int64.of_int y in
if Int64.compare y 0x248L = 1 then
invalid_arg "out of range" ;
Int64.mul year y
let of_f f =
if f < 0. then
invalid_arg "negative" ;
if f > 18446744073.709549 then
invalid_arg "out of range" ;
let s = Int64.of_float f in
let rem = f -. (Int64.to_float s) in
let ns = Int64.of_float (rem *. 1_000_000_000.) in
Int64.(add (mul 1_000_000_000L s) ns)
let to_f t =
let pl =
if t >= 0L then
0.
else
abs_float (2. *. (Int64.to_float 0x8000000000000000L))
in
let ns = Int64.to_float t in
(ns +. pl) /. 1_000_000_000.
let to_int64 t d =
let f c = Int64.div c d in
if t < 0L then
Int64.(add (f (Int64.add t Int64.min_int)) (add (f Int64.max_int) 1L))
else
f t
let to_int t d =
let r = to_int64 t d in
if r > Int64.of_int max_int then
invalid_arg "value too big for this platform" ;
Int64.to_int r
let to_us_64 t = to_int64 t 1_000L
let to_us t = to_int t 1_000L
let to_ms_64 t = to_int64 t 1_000_000L
let to_ms t = to_int t 1_000_000L
let to_sec_64 t = to_int64 t 1_000_000_000L
let to_sec t = to_int t 1_000_000_000L
let to_min t = to_int t 60_000_000_000L
let to_hour t = to_int t hour
let to_day t = to_int t day
let to_year t = to_int t year
let fields t =
let sec = to_sec_64 t in
let left = Int64.sub t (of_sec_64 sec) in
let ms = to_ms_64 left in
let left = Int64.sub left (of_ms_64 ms) in
let us = to_us_64 left in
let ns = Int64.(sub left (of_us_64 us)) in
(sec, ms, us, ns)
let pp ppf t =
let min = to_min t in
if min > 0 then
let y = to_year t in
let left = Int64.rem t year in
let d = to_day left in
let left = Int64.rem left day in
if y > 0 then
Format.fprintf ppf "%da%dd" y d
else
let h = to_hour left in
let left = Int64.rem left hour in
if d > 0 then
Format.fprintf ppf "%dd%02dh" d h
else
let min = to_min left in
let left = Int64.sub t (of_min min) in
let sec = to_sec left in
if h > 0 then
Format.fprintf ppf "%dh%02dm" h min
else (* if m > 0 then *)
Format.fprintf ppf "%dm%02ds" min sec
else (* below one minute *)
let s, ms, us, ns = fields t in
if s > 0L then
Format.fprintf ppf "%Ld.%03Lds" s ms
else if ms > 0L then
Format.fprintf ppf "%Ld.%03Ldms" ms us
else (* if us > 0 then *)
Format.fprintf ppf "%Ld.%03Ldμs" us ns