-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil_weekend.ml
112 lines (91 loc) · 2.6 KB
/
util_weekend.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
(*
Add or subtract work days to a date, skipping weekends.
It could be extended to support holidays or other weekend definitions
than Saturday-Sunday.
*)
module Param = struct
type date = Util_dateonly.t * Util_timeonly.t
let string_of_date (a, b) =
Printf.sprintf "%s, %s"
(Util_dateonly.to_string a) (Util_timeonly.to_string b)
let deconstruct (date_only, time_only) =
((date_only, Util_timeonly.of_float 0.),
Util_timeonly.to_float time_only)
let reconstruct (date_only, old_time_only) time_only =
assert (Util_timeonly.to_float old_time_only = 0.);
(date_only, Util_timeonly.of_float time_only)
let add_day (date_only, time_only) =
(Util_dateonly.next_day date_only, time_only)
let sub_day (date_only, time_only) =
(Util_dateonly.previous_day date_only, time_only)
end
module Workday = Util_workday.Make (Param)
let is_workday (date_only, time_only) =
match Util_dateonly.day_of_the_week date_only with
| 0 | 6 ->
(* Sunday | Saturday *)
false
| 1 | 2 | 3 | 4 | 5 ->
(* Monday-Friday *)
true
| _ -> assert false
let to_localtime ~timezone t =
let local = Util_localtime.of_utc ~timezone t in
Util_localtime.to_pair local
let of_localtime ~timezone (date_only, time_only) =
let local = Util_localtime.of_pair ~timezone date_only time_only in
Util_localtime.to_utc local
(*
Add workday-time (in seconds) to a date.
*)
let add ~timezone t workday_time =
of_localtime ~timezone (
Workday.add
~is_workday
(to_localtime ~timezone t)
workday_time
)
(*
Subtract workday-time (in seconds) from a date.
*)
let sub ~timezone t workday_time =
of_localtime ~timezone (
Workday.sub
~is_workday
(to_localtime ~timezone t)
workday_time
)
let test_weekend () =
(* Daylight savings time change in California on March 12, 2017. *)
let timezone = Util_timezone.of_string "America/Los_Angeles" in
(* Dates across the time change. Note the time of the day is the same
despite the time change. *)
let t1 = Util_time.of_string "2017-03-10T09:00:00-08:00" in
let t2 = Util_time.of_string "2017-03-17T09:00:00-07:00" in
let eq a b = Util_time.compare a b = 0 in
let time_shift =
(Util_time.to_float t2 -. Util_time.to_float t1) -. 7. *. 86400.
in
assert (time_shift = -3600.);
(* Subtract 5 workdays from t2 *)
assert (
eq t1 (
sub
~timezone
t2
(5. *. 86400.)
)
);
(* Add 5 workdays to t1 *)
assert (
eq t2 (
add
~timezone
t1
(5. *. 86400.)
)
);
true
let tests = [
"weekend", test_weekend;
]