Source file ym.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
type t = { month_count : int }

let equal (x : t) (y : t) = x.month_count = y.month_count

let lt (x : t) (y : t) = x.month_count < y.month_count

let le (x : t) (y : t) = x.month_count <= y.month_count

let gt (x : t) (y : t) = x.month_count > y.month_count

let ge (x : t) (y : t) = x.month_count >= y.month_count

let compare (x : t) (y : t) = compare x.month_count y.month_count

let month_count_of_ym ~year ~month = (year * 12) + (month - 1)

let ym_of_month_count month_count =
  if month_count >= 0 then (month_count / 12, (month_count mod 12) + 1)
  else ((month_count - 11) / 12, (((month_count mod 12) + 12) mod 12) + 1)

type error =
  [ `Does_not_exist
  | `Invalid_year of int
  | `Invalid_month of int
  ]

exception Error_exn of error

let make ~year ~month : (t, error) result =
  if year < Constants.min_year || Constants.max_year < year then
    Error (`Invalid_year year)
  else if month < 1 || 12 < month then Error (`Invalid_month month)
  else Ok { month_count = month_count_of_ym ~year ~month }

let make_exn ~year ~month : t =
  match make ~year ~month with Error e -> raise (Error_exn e) | Ok x -> x

let sub_month_count (t : t) n : t = { month_count = t.month_count - n }

let sub ?(years = 0) ?(months = 0) t : t =
  sub_month_count t ((years * 12) + months)

let add_month_count (t : t) n : t = { month_count = t.month_count + n }

let add ?(years = 0) ?(months = 0) t : t =
  add_month_count t ((years * 12) + months)

let diff_months t1 t2 = t1.month_count - t2.month_count

let year_month (t : t) : int * int = ym_of_month_count t.month_count

let year (t : t) : int = fst @@ year_month t

let month (t : t) : int = snd @@ year_month t