Source file duration_private.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
module P = Stdlib

module O : sig
  type t

  val ( * ) : t -> t -> t

  val ( + ) : t -> t -> t

  val ( - ) : t -> t -> t

  val ( / ) : t -> t -> t

  val abs : t -> t

  val of_int : int -> t

  val of_float : float -> t

  val compare : t -> t -> int

  val lt : t -> t -> bool

  val le : t -> t -> bool

  val gt : t -> t -> bool

  val ge : t -> t -> bool

  val to_string : t -> string

  val zero : t

  val one : t

  val to_float : t -> float

  val to_int : t -> int

  val div : t -> t -> int * t
end = struct
  type t = float

  let ( * ) = ( *. )

  let ( + ) = ( +. )

  let ( - ) = ( -. )

  let ( / ) = ( /. )

  let abs = abs_float

  let of_int = float_of_int

  let of_float x = x

  let compare (a : float) (b : float) = compare a b

  let lt a b = compare a b < 0

  let le a b = compare a b <= 0

  let gt a b = compare a b > 0

  let ge a b = compare a b >= 0

  let to_string x = string_of_int (int_of_float x)

  let zero = 0.0

  let one = 1.0

  let to_float x = x

  let to_int x = int_of_float x

  let div duration diviseur =
    let d = duration / diviseur in
    if lt (abs d) one then (0, duration)
    else (int_of_float d, mod_float duration diviseur)
end

open O

let ms_in_ms = of_int 1

let ms_in_s = of_int 1000

let s_in_s = of_int 1

let s_in_min = of_int 60

let ms_in_min = ms_in_s * s_in_min

let min_in_hour = of_int 60

let ms_in_hour = ms_in_min * min_in_hour

let hour_in_day = of_int 24

let ms_in_day = ms_in_hour * hour_in_day

let day_in_week = of_int 7

let ms_in_week = ms_in_day * day_in_week

let day_in_year = of_float 365.24219879

let month_in_year = of_int 12

let day_in_month = day_in_year / month_in_year

let ms_in_month = ms_in_day * day_in_month

let ms_in_year = ms_in_day * day_in_year

let fact_of_directive = function
  | 'x' -> ms_in_ms
  | 's' -> ms_in_s
  | 'm' -> ms_in_min
  | 'h' -> ms_in_hour
  | 'D' -> ms_in_day
  | 'W' -> ms_in_week
  | 'M' -> ms_in_month
  | 'Y' -> ms_in_year
  | _ -> assert false

let apply_directive dir d =
  let units = fact_of_directive dir in
  let dv = d in
  let fwd = ge dv (of_int 0) in
  let update = if fwd then ( - ) else ( + ) in
  let v' = abs dv / units in
  if lt v' one then (d, zero)
  else
    let new_d = update d (v' * units) in
    (new_d, v')

let static_printer s : O.t -> O.t -> string = fun _ _ -> s

let empty_printer = static_printer ""

let show_value (w : int) (_d : O.t) v =
  let str = to_string v in
  let i = P.( - ) w (String.length str) in
  if i > 0 then String.make i '0' ^ str else str

let check_condition cmp int true' false' =
  let false' = match false' with None -> empty_printer | Some y -> y in
  let cmp =
    match cmp with `EQ -> ( = ) | `NEQ -> ( <> ) | `LT -> ( < ) | `GT -> ( > )
  in
  fun d v -> if cmp (to_int v) int then true' d v else false' d v

let check_condition_simple cmp true' =
  let cmp : int -> bool =
    match cmp with
    | `EQ i -> ( = ) i
    | `LT -> fun i -> i < 0
    | `GT -> fun i -> i > 0
  in
  fun (d : O.t) (v : O.t) -> if cmp (O.to_int d) then true' d v else ""

let directive_block (dir : char) expr (d : O.t) _v =
  let nd, nv = apply_directive dir d in
  expr nd nv