159 lines
3.7 KiB
OCaml
159 lines
3.7 KiB
OCaml
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
|