0 | module IotaTime.CalendarDateTime
2 | import IotaTime.Calendar
3 | import IotaTime.Internal.ApplyPeriod
4 | import IotaTime.LocalTime
5 | import IotaTime.Period
9 | nanosecondsPerDay : Integer
10 | nanosecondsPerDay = 86400 * 1000000000
14 | record CalendarDateTimeRep (calendar : Type) (cal : Calendar calendar) where
15 | constructor MkCalendarDateTime
16 | date : CalendarDate calendar @{cal}
21 | CalendarDateTime : (calendar : Type) -> {auto cal : Calendar calendar} -> Type
22 | CalendarDateTime calendar @{cal} = CalendarDateTimeRep calendar cal
25 | {calendar : Type} -> {cal : Calendar calendar} ->
26 | Eq (CalendarDate calendar @{cal}) =>
27 | Eq (CalendarDateTimeRep calendar cal) where
28 | MkCalendarDateTime leftDate leftTime ==
29 | MkCalendarDateTime rightDate rightTime =
30 | leftDate == rightDate && leftTime == rightTime
33 | {calendar : Type} -> {cal : Calendar calendar} ->
34 | Ord (CalendarDate calendar @{cal}) =>
35 | Ord (CalendarDateTimeRep calendar cal) where
36 | compare left right = case compare left.date right.date of
37 | EQ => compare left.time right.time
38 | ordering => ordering
41 | {calendar : Type} -> {cal : Calendar calendar} ->
42 | Show (CalendarDate calendar @{cal}) =>
43 | Show (CalendarDateTimeRep calendar cal) where
44 | show value = "at (" ++ show value.date ++ ") (" ++ show value.time ++ ")"
48 | on : {calendar : Type} -> {auto cal : Calendar calendar} ->
49 | LocalTime -> CalendarDate calendar @{cal} -> CalendarDateTime calendar @{cal}
50 | on valueTime valueDate = MkCalendarDateTime valueDate valueTime
54 | at : {calendar : Type} -> {auto cal : Calendar calendar} ->
55 | CalendarDate calendar @{cal} -> LocalTime -> CalendarDateTime calendar @{cal}
56 | at valueDate valueTime = on valueTime valueDate
60 | atStartOfDay : {calendar : Type} -> {auto cal : Calendar calendar} ->
61 | CalendarDate calendar @{cal} -> CalendarDateTime calendar @{cal}
62 | atStartOfDay valueDate = at valueDate (localTime 0 0 0 0)
66 | datePart : {calendar : Type} -> {auto cal : Calendar calendar} ->
67 | CalendarDateTime calendar @{cal} -> CalendarDate calendar @{cal}
72 | localTimeOfDay : {calendar : Type} -> {auto cal : Calendar calendar} ->
73 | CalendarDateTime calendar @{cal} -> LocalTime
74 | localTimeOfDay = time
78 | atDatePart : {calendar : Type} -> {auto cal : Calendar calendar} ->
79 | (valueDate : CalendarDate calendar @{cal}) ->
80 | (valueTime : LocalTime) ->
81 | datePart @{cal} (at @{cal} valueDate valueTime) = valueDate
82 | atDatePart _ _ = Refl
86 | atLocalTimeOfDay : {calendar : Type} -> {auto cal : Calendar calendar} ->
87 | (valueDate : CalendarDate calendar @{cal}) ->
88 | (valueTime : LocalTime) ->
89 | localTimeOfDay @{cal} (at @{cal} valueDate valueTime) = valueTime
90 | atLocalTimeOfDay _ _ = Refl
94 | calendarDateTimeRoundTrip :
95 | {calendar : Type} -> {auto cal : Calendar calendar} ->
96 | (value : CalendarDateTime calendar @{cal}) ->
97 | at @{cal} (datePart @{cal} value) (localTimeOfDay @{cal} value) = value
98 | calendarDateTimeRoundTrip (MkCalendarDateTime _ _) = Refl
103 | withCalendar : {source : Type} -> {target : Type} ->
104 | {auto sourceCal : Calendar source} ->
105 | {auto targetCal : Calendar target} ->
106 | {auto sourceRep : HasCalendarBridge (CalendarDate source @{sourceCal})} ->
107 | {auto targetRep : HasCalendarBridge (CalendarDate target @{targetCal})} ->
108 | CalendarDateTime source @{sourceCal} ->
109 | Either CalendarConversionError (CalendarDateTime target @{targetCal})
110 | withCalendar @{sourceCal} @{targetCal} @{sourceRep} @{targetRep} value =
111 | map (\convertedDate => MkCalendarDateTime convertedDate value.time)
112 | (IotaTime.Calendar.withCalendar @{sourceRep} @{targetRep} value.date)
115 | implementation {calendar : Type} -> {cal : Calendar calendar} ->
116 | HasCalendar (CalendarDateTime calendar @{cal}) where
117 | calendarCapability = ()
120 | implementation {calendar : Type} -> {cal : Calendar calendar} ->
121 | HasTime (CalendarDateTime calendar @{cal}) where
122 | timeCapability = ()
125 | implementation {calendar : Type} -> {cal : Calendar calendar} ->
126 | PeriodTarget (CalendarDateTime calendar @{cal}) where
130 | implementation {calendar : Type} -> {cal : Calendar calendar} ->
131 | ApplyPeriod (CalendarDateTime calendar @{cal}) where
132 | applyPeriod period value =
133 | let dateAfterPeriod = applyCalendarPeriod @{cal} period value.date
134 | (carry, timeAfterPeriod) = applyTimePeriodWithCarry period value.time
135 | in MkCalendarDateTime (shiftCalendarDays @{cal} carry dateAfterPeriod) timeAfterPeriod
140 | between : {calendar : Type} -> {auto cal : Calendar calendar} ->
141 | (start : CalendarDateTime calendar @{cal}) ->
142 | (end : CalendarDateTime calendar @{cal}) ->
143 | Period (CalendarDateTime calendar @{cal})
144 | between @{cal} start end = nanoseconds
145 | ((toDaysFor @{cal} end.date - toDaysFor @{cal} start.date) * nanosecondsPerDay +
146 | toNanosecondsSinceMidnight end.time - toNanosecondsSinceMidnight start.time)