-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil_time.ml
212 lines (171 loc) · 5.12 KB
/
util_time.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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
type t = {
abstract_value: Util_abstract_value.t;
unixtime : float;
string : string;
}
let round x =
floor (x +. 0.5)
let round_milliseconds x =
1e-3 *. round (1e3 *. x)
let test_round_milliseconds () =
assert (round_milliseconds 8.01 = 8.01);
assert (round_milliseconds 3.0001 = 3.);
assert (round_milliseconds 123.4564 = 123.456);
assert (round_milliseconds 123.452 = 123.452);
assert (round_milliseconds 2.998 = 2.998);
assert (round_milliseconds 2.9998 = 3.);
assert (round_milliseconds (-1.9999) = -2.);
assert (round_milliseconds (-1.0001) = -1.);
assert (round_milliseconds (-1.23451) = -1.235);
assert (round_milliseconds (-1.23449) = -1.234);
assert (round_milliseconds 1385625519.658 = 1385625519.658);
true
let of_float t =
let t = round_milliseconds t in
{
abstract_value = Util_abstract_value.create ();
unixtime = t;
string =
Nldate.mk_internet_date
~localzone:true ~digits:3
(t +. 0.0005);
}
let to_float x = x.unixtime
let parse s =
try
Some (of_float (Nldate.since_epoch_approx (Nldate.parse s)))
with _ -> None
let of_string s =
match parse s with
None -> invalid_arg ("Util_time.of_string_exn: " ^ s)
| Some x -> x
let to_string x = x.string
let now () = of_float (Unix.gettimeofday ())
(* Convenience methods to get events for the entire day *)
let utc_start_of_week x =
let t = x.unixtime in
let tm = Unix.gmtime t in
let same_time_sunday = t -. float tm.Unix.tm_wday *. 86400. in
let t' = floor (same_time_sunday /. 86400.) *. 86400. in
of_float t'
let utc_week x =
(* week 0 = week containing 1970-01-01, starting 4 days earlier *)
let seconds_from_day0 = x.unixtime in
let days_from_week0 = seconds_from_day0 /. 86400. +. 4. in
truncate (days_from_week0 /. 7.)
let is_past x = x.unixtime < Unix.gettimeofday ()
let is_future x = x.unixtime > Unix.gettimeofday ()
let add x seconds = of_float (x.unixtime +. seconds)
let sub x seconds = of_float (x.unixtime -. seconds)
let add_min x minutes =
add x (minutes *. 60.)
let sub_min x minutes =
sub x (minutes *. 60.)
let add_hour x hours =
add x (hours *. 3600.)
let sub_hour x hours =
sub x (hours *. 3600.)
let add_day x days =
add x (days *. 86400.)
let sub_day x days =
sub x (days *. 86400.)
let test_add () =
let time = of_float 1424225951. in
let day_add = add_day time 9. in
let hour_add = add_hour time 9. in
let min_add = add_min time 9. in
let sec_add = add time 9. in
assert (day_add.unixtime = 1425003551.);
assert (hour_add.unixtime = 1424258351.);
assert (min_add.unixtime = 1424226491.);
assert (sec_add.unixtime = 1424225960.);
true
(* add a millisecond, or more if it's not enough to change the string
representation. *)
let next x =
let rec aux x increment =
let x' = add x increment in
if x'.string <> x.string then x'
else aux x (1.4 *. increment)
in
aux x 0.001
let wrap = of_string
let unwrap = to_string
let compare a b = Pervasives.compare a.unixtime b.unixtime
module Op = struct
let min a b = if compare a b <= 0 then a else b
let max a b = if compare a b >= 0 then a else b
let ( = ) a b = compare a b = 0
let ( < ) a b = compare a b < 0
let ( > ) a b = compare a b > 0
let ( <= ) a b = compare a b <= 0
let ( >= ) a b = compare a b >= 0
end
let diff_seconds a b =
let a_float = to_float a in
let b_float = to_float b in
let diff_seconds = a_float -. b_float in
diff_seconds
let diff_hours a b =
let diff_seconds = diff_seconds a b in
let diff_hours = diff_seconds /. 3600. in
diff_hours
let diff_days a b =
let diff_seconds = diff_seconds a b in
let diff_days = diff_seconds /. 86400. in
diff_days
let test_diffs () =
let eql a b =
abs_float (a -. b) < 0.001 in
let cur = now () in
let ten_minutes_from_now = add_min cur 10. in
let ten_days_from_now = add_day cur 10. in
assert (eql (diff_seconds ten_minutes_from_now cur) 600.);
assert (eql (diff_days ten_days_from_now cur) 10.);
true
let test_recover () =
let open Op in
let conv t =
let x1 = of_float t in
let x2 = of_string (to_string x1) in
x1 = x2
in
assert (conv 0.);
assert (conv 0.1000);
assert (conv 0.1001);
assert (conv 0.1002);
assert (conv 0.1003);
true
module As_unixtime = struct
type time = t
type t = time
let round_down = floor
let of_float = of_float
let to_float x =
round_down x.unixtime
let wrap = of_float
let unwrap = to_float
let of_string s =
of_float (float_of_string s)
let to_string x =
Printf.sprintf "%.0f" (to_float x)
let test_unixtime () =
assert (round_down 0.1 = 0.);
assert (round_down 0.9 = 0.);
assert (round_down (-0.1) = -1.);
assert (round_down (-10.1) = -11.);
assert (to_float (of_float 3.5) = 3.);
assert (to_string (of_float 3.5) = "3");
assert ((of_string "77.333").unixtime > 77.);
assert (to_float (of_string "77.333") = 77.);
assert (to_string (of_string "77.333") = "77");
true
end
include Op
let tests = [
"round milliseconds", test_round_milliseconds;
"recover", test_recover;
"unixtime", As_unixtime.test_unixtime;
"update times", test_add;
"diffs", test_diffs;
]