0 | module IotaTime.LocalTime
2 | import public IotaTime.Time.Component
3 | import IotaTime.Internal.ApplyPeriod
4 | import IotaTime.Period
8 | nanosPerSecond : Integer
9 | nanosPerSecond = 1000000000
11 | nanosPerDay : Integer
12 | nanosPerDay = 86400 * nanosPerSecond
16 | record LocalTime where
17 | constructor MkLocalTime
18 | nanosSinceMidnight : Integer
22 | left == right = left.nanosSinceMidnight == right.nanosSinceMidnight
26 | compare left right = compare left.nanosSinceMidnight right.nanosSinceMidnight
29 | toNanosecondsSinceMidnight : LocalTime -> Integer
30 | toNanosecondsSinceMidnight = nanosSinceMidnight
34 | localTime : Hour -> Minute -> Second -> Nanosecond -> LocalTime
35 | localTime valueHour valueMinute valueSecond valueNanosecond = MkLocalTime
36 | (((hourValue valueHour * 60 + minuteValue valueMinute) * 60 + secondValue valueSecond) *
37 | nanosPerSecond + nanosecondValue valueNanosecond)
41 | hour : LocalTime -> Hour
43 | hour value = either (const 0) id
44 | (refineHour (value.nanosSinceMidnight `div` (3600 * nanosPerSecond)))
48 | minute : LocalTime -> Minute
49 | minute value = either (const 0) id
50 | (refineMinute (value.nanosSinceMidnight `div` (60 * nanosPerSecond) `mod` 60))
54 | second : LocalTime -> Second
55 | second value = either (const 0) id
56 | (refineSecond (value.nanosSinceMidnight `div` nanosPerSecond `mod` 60))
60 | nanosecond : LocalTime -> Nanosecond
61 | nanosecond value = either (const 0) id
62 | (refineNanosecond (value.nanosSinceMidnight `mod` nanosPerSecond))
65 | Show LocalTime where
66 | show value = "localTime " ++
67 | show (hour value) ++ " " ++
68 | show (minute value) ++ " " ++
69 | show (second value) ++ " " ++
70 | show (nanosecond value)
75 | = InvalidHour HourError
76 | | InvalidMinute MinuteError
77 | | InvalidSecond SecondError
78 | | InvalidNanosecond NanosecondError
82 | refineLocalTime : Integer -> Integer -> Integer -> Integer -> Either LocalTimeError LocalTime
83 | refineLocalTime rawHour rawMinute rawSecond rawNanosecond = do
84 | valueHour <- mapFst InvalidHour (refineHour rawHour)
85 | valueMinute <- mapFst InvalidMinute (refineMinute rawMinute)
86 | valueSecond <- mapFst InvalidSecond (refineSecond rawSecond)
87 | valueNanosecond <- mapFst InvalidNanosecond (refineNanosecond rawNanosecond)
88 | pure (localTime valueHour valueMinute valueSecond valueNanosecond)
91 | applyTimePeriodWithCarry : Period target -> LocalTime -> (Integer, LocalTime)
92 | applyTimePeriodWithCarry period value =
93 | let combined = value.nanosSinceMidnight + delta
94 | carry = combined `div` nanosPerDay
95 | withinDay = combined `mod` nanosPerDay
96 | in (carry, MkLocalTime withinDay)
98 | delta = (((periodHours period * 60 + periodMinutes period) * 60 +
99 | periodSeconds period) * nanosPerSecond) + periodNanoseconds period
102 | HasTime LocalTime where
103 | timeCapability = ()
106 | PeriodTarget LocalTime where
110 | ApplyPeriod LocalTime where
111 | applyPeriod period = snd . applyTimePeriodWithCarry period
117 | between : (start : LocalTime) -> (end : LocalTime) -> Period LocalTime
118 | between start end = nanoseconds
119 | (toNanosecondsSinceMidnight end - toNanosecondsSinceMidnight start)