This repository has been archived by the owner on Sep 7, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 55
/
etime.ergo
232 lines (208 loc) · 9.24 KB
/
etime.ergo
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace org.accordproject.time
// DateTime operations
// Current DateTime
define function now() : DateTime
// Parse a DateTime
define function dateTime(x:String) : DateTime
// DateTime components
define function getSecond(x:DateTime) : Long
define function getMinute(x:DateTime) : Long
define function getHour(x:DateTime) : Long
define function getDay(x:DateTime) : Long
define function getWeek(x:DateTime) : Long
define function getMonth(x:DateTime) : Long
define function getQuarter(x:DateTime) : Long
define function getYear(x:DateTime) : Long
// Comparisons between dates
define function isAfter(x:DateTime, y:DateTime) : Boolean
define function isBefore(x:DateTime, y:DateTime) : Boolean
define function isSame(x:DateTime, y:DateTime) : Boolean
// Aggregate functions on dates
define function dateTimeMin(x:DateTime[]) : DateTime
define function dateTimeMax(x:DateTime[]) : DateTime
// Durations
define function durationSeconds(x:Long) : InternalDuration
define function durationMinutes(x:Long) : InternalDuration
define function durationHours(x:Long) : InternalDuration
define function durationDays(x:Long) : InternalDuration
define function durationWeeks(x:Long) : InternalDuration
define function durationToInternalDuration(du:Duration) : InternalDuration {
match du.unit
with seconds then return durationSeconds(du.amount)
with minutes then return durationMinutes(du.amount)
with hours then return durationHours(du.amount)
with ~org.accordproject.time.TemporalUnit.days then return durationDays(du.amount)
with ~org.accordproject.time.TemporalUnit.weeks then return durationWeeks(du.amount)
else return durationSeconds(du.amount) // Defaults to seconds
}
define function durationAmount(du:InternalDuration) : Long
define function internalDurationToDuration(du:InternalDuration) : Duration {
return Duration{ unit: seconds, amount: durationAmount(du) }
}
// Cast a duration to a given temporal unit
define function durationAs(du:Duration, u:TemporalUnit) : Duration {
if u = du.unit
then return du
else
let amount =
match u
with seconds then
match du.unit
with minutes then du.amount * 60
with hours then du.amount * 60 * 60
with ~org.accordproject.time.TemporalUnit.days then du.amount * 60 * 60 * 24
with ~org.accordproject.time.TemporalUnit.weeks then du.amount * 60 * 60 * 24 * 7
else du.amount // Default to seconds
with minutes then
match du.unit
with seconds then du.amount / 60
with hours then du.amount * 60
with ~org.accordproject.time.TemporalUnit.days then du.amount * 60 * 24
with ~org.accordproject.time.TemporalUnit.weeks then du.amount * 60 * 24 * 7
else du.amount * 60 // Default to seconds
with hours then
match du.unit
with seconds then du.amount / 60 / 60
with minutes then du.amount * 60
with ~org.accordproject.time.TemporalUnit.days then du.amount * 24
with ~org.accordproject.time.TemporalUnit.weeks then du.amount * 24 * 7
else du.amount * 60 * 60 // Default to seconds
with ~org.accordproject.time.TemporalUnit.days then
match du.unit
with seconds then du.amount / 60 / 60 / 24
with minutes then du.amount * 60 / 24
with hours then du.amount / 24
with ~org.accordproject.time.TemporalUnit.weeks then du.amount * 7
else du.amount / 60 / 60 / 24 // Default to seconds
with ~org.accordproject.time.TemporalUnit.weeks then
match du.unit
with seconds then du.amount / 60 / 60 / 24 / 7
with minutes then du.amount * 60 / 24 / 7
with hours then du.amount / 24 / 7
with ~org.accordproject.time.TemporalUnit.days then du.amount / 7
else du.amount / 60 / 60 / 24 / 7 // Default to seconds
else // Default to seconds
match du.unit
with minutes then du.amount * 60
with hours then du.amount * 60 * 60
with ~org.accordproject.time.TemporalUnit.days then du.amount * 60 * 60 * 24
with ~org.accordproject.time.TemporalUnit.weeks then du.amount * 60 * 60 * 24 * 7
else du.amount // Default to seconds
;
return Duration{ unit: u, amount: amount }
}
// Duration difference between two dates
define function diffInternal(x:DateTime, y:DateTime) : InternalDuration
define function diffDurationAs(x:DateTime, y:DateTime, z:TemporalUnit) : Duration {
return durationAs(internalDurationToDuration(diffInternal(x,y)),z)
}
define function diffDuration(x:DateTime, y:DateTime) : Duration {
return diffDurationAs(x, y, seconds) // Defaults to seconds
}
// Add and subtract durations
define function addInternal(x:DateTime, y:InternalDuration) : DateTime
define function addDuration(x:DateTime, y:Duration) : DateTime {
return addInternal(x,durationToInternalDuration(y))
}
define function subtractInternal(x:DateTime, y:InternalDuration) : DateTime
define function subtractDuration(x:DateTime, y:Duration) : DateTime {
return subtractInternal(x,durationToInternalDuration(y))
}
define function divideDuration(x:Duration, y:Duration) : Double {
let du1 = durationToInternalDuration(x);
let du2 = durationToInternalDuration(y);
return longToDouble(durationAmount(du1)) / longToDouble(durationAmount(du2))
}
// Periods
define function periodDays(x:Long) : InternalPeriod
define function periodWeeks(x:Long) : InternalPeriod
define function periodMonths(x:Long) : InternalPeriod
define function periodQuarters(x:Long) : InternalPeriod
define function periodYears(x:Long) : InternalPeriod
define function periodToInternalPeriod(du:Period) : InternalPeriod {
match du.unit
with days then return periodDays(du.amount)
with weeks then return periodWeeks(du.amount)
with months then return periodMonths(du.amount)
with quarters then return periodQuarters(du.amount)
with years then return periodYears(du.amount)
else return periodDays(du.amount) // Defaults to days
}
// Period difference between two dates
define function diffAsMonths(x:DateTime, y:DateTime) : Long {
let year = getYear(x) - getYear(y);
let month = getMonth(x) - getMonth(y);
return year * 12 + month
}
define function diffPeriodAs(x:DateTime, y:DateTime, z:PeriodUnit) : Period {
match z
with days
then let d = diffDurationAs(x,y,~org.accordproject.time.TemporalUnit.days);
return Period{ amount: d.amount, unit: days }
with ~org.accordproject.time.PeriodUnit.weeks
then let w = diffDurationAs(x,y,~org.accordproject.time.TemporalUnit.weeks);
return Period{ amount: w.amount, unit: weeks }
with months then let m = diffAsMonths(x,y); return Period{ amount: m, unit: months }
with quarters then let m = diffAsMonths(x,y); return Period{ amount: m / 3, unit: quarters }
with years then let m = diffAsMonths(x,y); return Period{ amount: m / 12, unit: years }
else
let d = diffDurationAs(x,y,~org.accordproject.time.TemporalUnit.days);
return Period{ amount: d.amount, unit: days }
}
// Add and subtract periods
define function addInternalPeriod(x:DateTime, y:InternalPeriod) : DateTime
define function addPeriod(x:DateTime, y:Period) : DateTime {
return addInternalPeriod(x,periodToInternalPeriod(y))
}
define function subtractInternalPeriod(x:DateTime, y:InternalPeriod) : DateTime
define function subtractPeriod(x:DateTime, y:Period) : DateTime {
return subtractInternalPeriod(x,periodToInternalPeriod(y))
}
// Move the date to the closest start or end of a period
define function startOfDay(x:DateTime) : DateTime
define function startOfWeek(x:DateTime) : DateTime
define function startOfMonth(x:DateTime) : DateTime
define function startOfQuarter(x:DateTime) : DateTime
define function startOfYear(x:DateTime) : DateTime
define function startOf(x:DateTime, y:PeriodUnit) : DateTime {
match y
with days then return startOfDay(x)
with weeks then return startOfWeek(x)
with months then return startOfMonth(x)
with quarters then return startOfQuarter(x)
with years then return startOfYear(x)
else return startOfDay(x) // Default to days
}
define function endOfDay(x:DateTime) : DateTime
define function endOfWeek(x:DateTime) : DateTime
define function endOfMonth(x:DateTime) : DateTime
define function endOfQuarter(x:DateTime) : DateTime
define function endOfYear(x:DateTime) : DateTime
define function endOf(x:DateTime, y:PeriodUnit) : DateTime {
match y
with days then return endOfDay(x)
with weeks then return endOfWeek(x)
with months then return endOfMonth(x)
with quarters then return endOfQuarter(x)
with years then return endOfYear(x)
else return endOfDay(x) // Default to days
}
// Format
define function dateTimeFormatInternal(x:String) : InternalFormat
define function formatInternal(x:DateTime,y:InternalFormat) : String
define function format(x:DateTime,y:String) : String {
return formatInternal(x,dateTimeFormatInternal(y))
}