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
59module Duets.Entities.Time
open FSharp.Data.UnitSystems.SI.UnitNames
open Duets.Common
let private secondsInMinute = 60<second / minute>
module Length =
/// Creates an empty length that indicates 0.
let empty =
{ Minutes = 0<minute>
Seconds = 0<second> }
type ValidationError =
| LessThan0Minutes
| LessThan0Seconds
| MoreThan60Seconds
| InvalidFormat
let private validateMinutes minutes =
if minutes >= 0<minute> then
Ok minutes
else
Error LessThan0Minutes
let private validateSeconds seconds =
if seconds < 0<second> then Error LessThan0Seconds
else if seconds > 60<second> then Error MoreThan60Seconds
else Ok seconds
/// Creates a length given the minutes and seconds, validating that a correct
/// length was passed.
let from minutes seconds =
validateMinutes minutes
|> Result.andThen (validateSeconds seconds)
|> Result.transform { Minutes = minutes; Seconds = seconds }
/// Creates a length from the given amount of seconds.
let fromSeconds (s: int<second>) =
let ts = System.TimeSpan.FromSeconds(float s)
from (ts.Minutes * 1<minute>) (ts.Seconds * 1<second>)
/// Creates a length given a string representing it with the format mm:ss,
/// such as 6:55, 0:35 or 3:00.
let parse (input: string) =
try
input.Split ':'
|> fun inputs ->
match inputs with
| [| minutes; seconds |] ->
from (int minutes * 1<minute>) (int seconds * 1<second>)
| _ -> Error InvalidFormat
with _ ->
Error InvalidFormat
/// Returns the total amount of seconds in the given length.
let inSeconds length =
length.Minutes * secondsInMinute + length.Seconds