0 | module IotaTime.Offset
2 | import public Data.So
6 | secondsPerMinute : Integer
7 | secondsPerMinute = 60
9 | secondsPerHour : Integer
10 | secondsPerHour = 3600
12 | maxOffsetHours : Integer
15 | maxOffsetSeconds : Integer
16 | maxOffsetSeconds = maxOffsetHours * secondsPerHour
21 | record OffsetRep where
22 | constructor MkOffset
23 | storedSeconds : Integer
30 | isValidOffsetSeconds : Integer -> Bool
31 | isValidOffsetSeconds value =
32 | value >= -
64800 && value <= 64800
35 | isValidOffsetMinutes : Integer -> Bool
36 | isValidOffsetMinutes value =
37 | value >= -
1080 && value <= 1080
40 | isValidOffsetHours : Integer -> Bool
41 | isValidOffsetHours value =
42 | value >= -
18 && value <= 18
45 | fromSeconds : (value : Integer) ->
46 | {auto 0 valid : So (isValidOffsetSeconds value)} -> Offset
47 | fromSeconds value = MkOffset value
50 | fromMinutes : (value : Integer) ->
51 | {auto 0 valid : So (isValidOffsetMinutes value)} -> Offset
52 | fromMinutes value = MkOffset (value * secondsPerMinute)
55 | fromHours : (value : Integer) ->
56 | {auto 0 valid : So (isValidOffsetHours value)} -> Offset
57 | fromHours value = MkOffset (value * secondsPerHour)
60 | data OffsetError = OffsetOutOfRange Integer
63 | refineOffsetSeconds : (value : Integer) -> Either OffsetError Offset
64 | refineOffsetSeconds value =
65 | case choose (isValidOffsetSeconds value) of
66 | Left valid => Right (fromSeconds value @{valid})
67 | Right _ => Left (OffsetOutOfRange value)
72 | totalOffsetSeconds : Offset -> Integer
73 | totalOffsetSeconds (MkOffset value) = value
75 | componentSign : Integer -> Integer
76 | componentSign value = if value < 0 then -
1 else 1
80 | hours : Offset -> Integer
82 | componentSign seconds * (abs seconds `div` secondsPerHour)
84 | seconds = totalOffsetSeconds value
88 | minutes : Offset -> Integer
90 | componentSign seconds *
91 | ((abs seconds `mod` secondsPerHour) `div` secondsPerMinute)
93 | seconds = totalOffsetSeconds value
97 | seconds : Offset -> Integer
99 | componentSign seconds * (abs seconds `mod` secondsPerMinute)
101 | seconds = totalOffsetSeconds value
107 | clampOffsetSeconds : Integer -> Integer
108 | clampOffsetSeconds value = max (-
64800) (min 64800 value)
112 | addClamped : Offset -> Offset -> Offset
113 | addClamped left right = MkOffset (clampOffsetSeconds
114 | (totalOffsetSeconds left + totalOffsetSeconds right))
118 | minusClamped : Offset -> Offset -> Offset
119 | minusClamped left right = MkOffset (clampOffsetSeconds
120 | (totalOffsetSeconds left - totalOffsetSeconds right))
124 | negateOffset : Offset -> Offset
125 | negateOffset value = MkOffset (negate (totalOffsetSeconds value))
129 | left == right = totalOffsetSeconds left == totalOffsetSeconds right
132 | Ord OffsetRep where
133 | compare left right = compare
134 | (totalOffsetSeconds left) (totalOffsetSeconds right)
137 | Show OffsetRep where
138 | show value = "fromSeconds " ++ show (totalOffsetSeconds value)