package mtime

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file mtime.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
(*---------------------------------------------------------------------------
   Copyright (c) 2015 The mtime programmers. All rights reserved.
   Distributed under the ISC license, see terms at the end of the file.
  ---------------------------------------------------------------------------*)

(* Time scale conversion *)

let ns_to_s   = 1e-9
let us_to_s   = 1e-6
let ms_to_s   = 1e-3
let min_to_s  = 60.
let hour_to_s = 3600.
let day_to_s  = 86_400.
let year_to_s = 31_557_600.

let s_to_ns   = 1e9
let s_to_us   = 1e6
let s_to_ms   = 1e3
let s_to_min  = 1. /. min_to_s
let s_to_hour = 1. /. hour_to_s
let s_to_day  = 1. /. day_to_s
let s_to_year = 1. /. year_to_s

(* Time spans

   Time spans are in nanoseconds and we represent them by an unsigned
   64-bit integer. This allows to represent spans for:
   (2^64-1) / 1_000_000_000 / (24 * 3600 * 365.25) ≅ 584.5 Julian years *)

type span = int64 (* unsigned nanoseconds *)

module Span = struct
  type t = span
  let zero = 0L
  let one = 1L
  let min_span = zero
  let max_span = -1L

  (* Predicates *)

  let equal = Int64.equal
  let compare = Int64.unsigned_compare

  (* Arithmetic *)

  let add = Int64.add
  let abs_diff s0 s1 =
    if compare s0 s1 < 0 then Int64.sub s1 s0 else Int64.sub s0 s1

  (* Durations *)

  let ( * ) n s = Int64.mul (Int64.of_int n) s
  let ns   =                      1L
  let us   =                  1_000L
  let ms   =              1_000_000L
  let s    =          1_000_000_000L
  let min  =         60_000_000_000L
  let hour =       3600_000_000_000L
  let day  =      86400_000_000_000L
  let year = 31_557_600_000_000_000L

  (* Converting *)

  let to_uint64_ns s = s
  let of_uint64_ns ns = ns

  let unsafe_of_uint64_ns_option nsopt = nsopt

  let to_ns s = (Int64.to_float s)
  let to_us s = (Int64.to_float s) *. 1e-3
  let to_ms s = (Int64.to_float s) *. 1e-6
  let to_s  s = (Int64.to_float s) *. 1e-9

  let ns_to_min = ns_to_s *. s_to_min
  let to_min s = (Int64.to_float s) *. ns_to_min

  let ns_to_hour = ns_to_s *. s_to_hour
  let to_hour s = (Int64.to_float s) *. ns_to_hour

  let ns_to_day = ns_to_s *. s_to_day
  let to_day s = (Int64.to_float s) *. ns_to_day

  let ns_to_year = ns_to_s *. s_to_year
  let to_year s = (Int64.to_float s) *. ns_to_year

  (* Formatting

     Maybe one day we could replace this by B00_std.Fmt.uint64_ns_span
     which does all the arithmetic on uint64. *)

  let round x = floor (x +. 0.5)
  let round_dfrac d x =             (* rounds [x] to the [d]th decimal digit *)
    if x -. (round x) = 0. then x else                   (* x is an integer. *)
    let m = 10. ** (float d) in                       (* m moves 10^-d to 1. *)
    (floor ((x *. m) +. 0.5)) /. m

  let pp_float_s ppf span =
    let m = abs_float span in
    if m < ms_to_s then
      (* m < 1ms, if <  100us, print us with 3 frac digit w.o. trailing zeros
                  if >= 100us, print us without frac digit *)
      let us = span /. us_to_s in
      let us = if abs_float us < 100. then round_dfrac 3 us else round us in
      if abs_float us >= 1000. then Format.fprintf ppf "%gms" (copysign 1. us)
      else Format.fprintf ppf "%gus" us
    else if m < 1. then
      (* m < 1s, if <  100ms, print ms with 3 frac digit w.o. trailing zeros
                 if >= 100ms, print ms without frac digit *)
      let ms = span /. ms_to_s in
      let ms = if abs_float ms < 100. then round_dfrac 3 ms else round ms in
      if abs_float ms >= 1000. then Format.fprintf ppf "%gs" (copysign 1. ms)
      else Format.fprintf ppf "%gms" ms
    else if m < min_to_s then
      (* m < 1min, print [s] with 3 frac digit w.o. trailing zeros *)
      let s = round_dfrac 3 span in
      if abs_float s >= 60. then Format.fprintf ppf "%gmin" (copysign 1. s)
      else Format.fprintf ppf "%gs" s
    else
    (* m >= 1min
       From here on we show the two (or one if the second is zero) largest
       significant units and no longer care about rounding the lowest unit,
       we just truncate. *)
    if m < hour_to_s then
      let m, rem = truncate (span /. min_to_s), mod_float span min_to_s in
      let s = truncate rem in
      if s = 0 then Format.fprintf ppf "%dmin" m else
      Format.fprintf ppf "%dmin%ds" m (abs s)
    else if m < day_to_s then
      let h, rem = truncate (span /. hour_to_s), mod_float span hour_to_s in
      let m = truncate (rem /. min_to_s) in
      if m = 0 then Format.fprintf ppf "%dh" h else
      Format.fprintf ppf "%dh%dmin" h (abs m)
    else if m < year_to_s then
      let d, rem = truncate (span /. day_to_s), mod_float span day_to_s in
      let h = truncate (rem /. hour_to_s) in
      if h = 0 then Format.fprintf ppf "%dd" d else
      Format.fprintf ppf "%dd%dh" d (abs h)
    else
    let y, rem = truncate (span /. year_to_s), mod_float span year_to_s in
    let d = truncate (rem /. day_to_s) in
    if d = 0 then Format.fprintf ppf "%da" y else
    Format.fprintf ppf "%da%dd" y (abs d)

  let pp ppf s = pp_float_s ppf (to_s s)
  let dump ppf s = Format.fprintf ppf "%Lu" s
end

(* Monotonic timestamps *)

type t = int64

let to_uint64_ns s = s
let of_uint64_ns ns = ns
let min_stamp = 0L
let max_stamp = -1L

(* Predicates *)

let equal = Int64.equal
let compare = Int64.unsigned_compare
let is_earlier t ~than = compare t than < 0
let is_later t ~than = compare t than > 0

(* Arithmetic *)

let span t0 t1 = if compare t0 t1 < 0 then Int64.sub t1 t0 else Int64.sub t0 t1

let add_span t s =
  let sum = Int64.add t s in
  if compare t sum <= 0 then Some sum else None

let sub_span t s =
  if compare t s < 0 then None else Some (Int64.sub t s)

(* Formatters *)

let pp ppf ns = Format.fprintf ppf "%Luns" ns
let dump ppf ns = Format.fprintf ppf "%Lu" ns

(*---------------------------------------------------------------------------
   Copyright (c) 2015 The mtime programmers

   Permission to use, copy, modify, and/or distribute this software for any
   purpose with or without fee is hereby granted, provided that the above
   copyright notice and this permission notice appear in all copies.

   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  ---------------------------------------------------------------------------*)