Used colon-less keyword syntax in method signatures where the optional variable name...
[cslatevm.git] / src / lib / time.slate
blobe64c042335b2565970c0c5b373c36d2a3ccdb358
2 "Date and Time protocols, included from ANSI Smalltalk packages for Squeak."
4 prototypes ensureNamespace: #time &delegate: True.
6 time define: #ticksPerSecond -> 1000000.
8 time define: #Time &parents: {Comparable} &slots: {#secondsSinceMidnight -> 0}.
9 "Time represents a point within a 24-hour period, stored as seconds since midnight."
11 time define: #Duration &parents: {Comparable} &slots: {#totalSeconds -> 0}.
12 "Duration represents a span of time with no particular fixed start point."
14 _@time ticksSinceEpoch [lobby timeSinceEpoch as: Integer].
16 m@(Method traits) timeToRun &count
17 "Returns the number of seconds to execute the method once."
18 [| end |
19   start ::= time `cache ticksSinceEpoch.
20   countWasGiven ::= count isNotNil.
21   count `defaultsTo: 1.
22   lobby collectGarbage. "Minimize the dynamic effect of the heap state."
23   countWasGiven ifTrue: [[count timesRepeat: m] ensure: [end := time ticksSinceEpoch]]
24                 ifFalse: [[m do] ensure: [end := time ticksSinceEpoch]].
25   end - start / time ticksPerSecond / count as: Float
28 m@(Method traits) duration
30   Duration newForSeconds: m timeToRun / 1000
33 Time traits compareAndHashUsingSlots: #{#secondsSinceMidnight}.
34 Duration traits compareAndHashUsingSlots: #{#totalSeconds}.
36 t@(Time traits) newForSeconds: n
37 [t clone `setting: #{#secondsSinceMidnight} to: {n}].
39 t@(Time traits) newForHours: h minutes: m seconds: s
40 [t clone `setting: #{#secondsSinceMidnight} to: {h * SecondsInHour + (m * SecondsInMinute) + s}].
42 d@(Duration traits) newForSeconds: n
43 [d clone `setting: #{#totalSeconds} to: {n}].
45 d@(Duration traits) newForDays: n [d newForSeconds: n * SecondsInDay].
46 d@(Duration traits) newForHours: n [d newForSeconds: n * SecondsInHour].
47 d@(Duration traits) newForMinutes: n [d newForSeconds: n * SecondsInMinute].
49 t@(Time traits) as: d@(Duration traits)
50 [d newForSeconds: t secondsSinceMidnight].
52 d@(Duration traits) as: t@(Time traits)
53 [t newForSeconds: d totalSeconds].
55 t@(Time traits) days [(t as: Duration) days].
56 t@(Time traits) hours [(t as: Duration) hours].
57 t@(Time traits) minutes [(t as: Duration) minutes].
58 t@(Time traits) seconds [(t as: Duration) seconds].
60 d@(Duration traits) days
61 "The number of whole days represented, possibly negative."
63   d totalSeconds abs // SecondsInDay * d totalSeconds sign
66 d@(Duration traits) hours
67 "The number of whole hours represented, possibly negative, after whole days
68 are discounted."
70   d totalSeconds abs \\ SecondsInDay // SecondsInHour * d totalSeconds sign
73 d@(Duration traits) minutes
74 "The number of whole minutes, possibly negative, after whole days and hours
75 are discounted."
77   d totalSeconds abs \\ SecondsInHour // SecondsInMinute * d totalSeconds sign
80 d@(Duration traits) seconds
81 "The number of seconds, possibly negative, after whole days, hours, minutes
82 are discounted."
84   d totalSeconds abs \\ SecondsInMinute * d totalSeconds sign
87 t@(Time traits) + d@(Duration traits)
89   t newForSeconds: t secondsSinceMidnight + d totalSeconds
92 t1@(Time traits) - t2@(Time traits)
94   Duration newForSeconds: t1 secondsSinceMidnight - t2 secondsSinceMidnight
97 t1@(Time traits) < t2@(Time traits)
99   t1 secondsSinceMidnight < t2 secondsSinceMidnight
102 d@(Duration traits) * n@(Number traits)
104   d newForSeconds: d totalSeconds * n
107 d@(Duration traits) / n@(Number traits)
109   d newForSeconds: d totalSeconds / n
112 d1@(Duration traits) / d2@(Duration traits)
114   d1 totalSeconds / d2 totalSeconds
117 d1@(Duration traits) + d2@(Duration traits)
119   d1 newForSeconds: d1 totalSeconds + d2 totalSeconds
122 d1@(Duration traits) - d2@(Duration traits)
124   d1 newForSeconds: d1 totalSeconds - d2 totalSeconds
127 d@(Duration traits) abs
129   d newForSeconds: d totalSeconds abs
132 d@(Duration traits) negated
134   d newForSeconds: d totalSeconds negated
137 d@(Duration traits) isZero
139   d totalSeconds isZero
142 t@(Time traits) isMidnight
144   d secondsSinceMidnight isZero
147 d@(Duration traits) sign
149   d totalSeconds sign
152 d@(Duration traits) isPositive
154   d totalSeconds isPositive
157 d@(Duration traits) isNegative
159   d totalSeconds isNegative
162 d1@(Duration traits) < d2@(Duration traits)
164   d1 totalSeconds < d2 totalSeconds
167 d1@(Duration traits) > d2@(Duration traits)
169   d1 totalSeconds > d2 totalSeconds
172 d@(Duration traits) printAbsOn: stream
174   stream
175     ; (d days abs printString)
176     ; ':'
177     ; (d hours abs printString truncateTo: 2 paddedBy: $0)
178     ; ':'
179     ; (d minutes abs printString truncateTo: 2 paddedBy: $0)
180     ; ':'
181     ; (d seconds abs printString truncateTo: 2 paddedBy: $0).
182   d
185 d@(Duration traits) printOn: stream
186 "Prints out the format [-]D:HH:MM:SS[.S] ."
188   d totalSeconds isNegative ifTrue: [stream nextPut: $-].
189   d printAbsOn: stream
192 time define: #Date &parents: {Comparable} &slots: {#julianDayNumber}.
194 time define: #MonthNames -> #{#January. #February. #March. #April. #May. #June. #July. #August. #September. #October. #December}.
195 time define: #WeekDayNames -> #{#Sunday. #Monday. #Tuesday. #Wednesday. #Thursday. #Friday}.
197 time define: #Month &parents: {Cloneable}
198   &slots: {#name -> ''. #firstDayWithinYear -> 0. #length -> 0}.
200 m@(Month traits) newNamed: name startingAt: start length: length
201 [m clone `setting: #{#name. #firstDayWithinYear. #length}
202    to: {name. start. length}].
204 m@(Month traits) newNamed: name from: start to: end
205 [m newNamed: name startingAt: start length: end - start + 1].
207 m@(Month traits) abbreviation
208 [m name first: 3].
210 time ensureNamespace: #months &slots:
211   {#January -> (Month newNamed: 'January' startingAt: 1 length: 31).
212    #February -> (Month newNamed: 'February' startingAt: 32 length: 28).
213    #March -> (Month newNamed: 'March' startingAt: 60 length: 31).
214    #April -> (Month newNamed: 'April' startingAt: 91 length: 30).
215    #May -> (Month newNamed: 'May' startingAt: 121 length: 31).
216    #June -> (Month newNamed: 'June' startingAt: 152 length: 30).
217    #July -> (Month newNamed: 'July' startingAt: 182 length: 31).
218    #August -> (Month newNamed: 'August' startingAt: 213 length: 31).
219    #September -> (Month newNamed: 'September' startingAt: 244 length: 30).
220    #October -> (Month newNamed: 'October' startingAt: 274 length: 31).
221    #November -> (Month newNamed: 'November' startingAt: 305 length: 30).
222    #December -> (Month newNamed: 'December' startingAt: 335 length: 31)}.
224 time define: #JulianMonths -> (Set new &capacity: 12).
225 months slotValuesDo: #(JulianMonths add: _) `er.
227 time define: #SecondsInMinute -> 60.
228 time define: #SecondsInHour -> (SecondsInMinute * 60).
229 time define: #SecondsInDay -> (SecondsInHour * 24).
231 time define: #Instant &parents: {Comparable}
232    &slots: {#localDate. #localOffsetToUTC. #localTime.
233             #localTimeZoneName. #localTimeZoneAbbrev}.
234 "Instant objects represent individual points in Coordinated Universal
235 Time (UTC) formerly called GMT at Greenwich, UK as represented in an
236 implementation defined local time, including consideration of time zones."
238 i@(Instant traits) dayOfMonth
239 "Answer an Integer between 1 and 31, inclusive, representing the day of the
240 month in the local time of the receiver, which includes the receiver."
241 [i localDate dayOfMonth].
243 i@(Instant traits) dayOfWeek
244 "Answer an Integer between 1 and 7, inclusive, representing the day of the
245 week in the local time of the receiver, which includes the receiver. Sunday
246 is 1, Monday 2, and so on."
248   (dayIndex ::= i localDate weekdayIndex + 1) > 7
249     ifTrue: [1] ifFalse: [dayIndex]
252 i@(Instant traits) dayOfWeekAbbreviation
254   i dayOfWeekName first: 3
257 i@(Instant traits) dayOfWeekName
258 "Answer the name of the day of the week in the local time."
260   i localDate weekday as: String
263 i@(Instant traits) dayOfYear
264 "Answer an Integer between 1 and 366, inclusive, representing the day of
265 the year in the local time of the receiver, which includes the receiver."
267   i localDate day
270 i@(Instant traits) hour
271 "Answer an Integer between 0 and 23, inclusive, representing the hour of the
272 day in the local time of the receiver. This may be in either the 12 or 24
273 hour clock."
275   i localTime hours
278 i@(Instant traits) hour24
280   i hour
283 i@(Instant traits) hour12
284 "Answer an Integer between 1 and 12, inclusive, representing the hour of the
285 day in the 12-hour clock of the local time of the receiver."
287   (tempHour ::= (i hour + 1) abs) > 12
288     ifTrue: [tempHour - 12]
289     ifFalse: [tempHour]
292 i@(Instant traits) minute
293 "Answer an Integer between 0 and 59, inclusive, representing the minute of
294 the hour in the local time of the receiver."
296   i localTime minutes
299 i@(Instant traits) second
300 "Answer an Integer between 0 and 59, inclusive, representing the second of
301 the minute in the local time of the receiver, including the fractional part."
303   i localTime seconds abs
306 i@(Instant traits) year
307 "Answer an Integer representing the year of the local time which includes
308 the receiver."
310   i localDate year
313 i@(Instant traits) month
314 "Answer an Integer between 1 and 12, inclusive, representing the month of
315 the year in the local time of the receiver."
317   i localDate monthIndex
320 i@(Instant traits) monthName
321 "Answer the name of the month of the year in the local time of the
322 receiver, which includes the receiver."
324   i localDate monthName as: String
327 i@(Instant traits) monthAbbreviation
328 "Answer a <readableString> which is the abbreviated name of the month of the
329 year in the local time of the receiver, which includes the receiver."
331   i monthName first: 3
334 i@(Instant traits) offset
336   i localOffsetToUTC
339 i@(Instant traits) offset: d@(Duration traits)
340 "Answer an Instant equivalent to the receiver, but with its local time
341 offset from UTC by the Duration."
343   d abs < Day
344     ifTrue: [i clone `setting: #{#localOffsetToUTC} to: {d}]
345     ifFalse: [i error: 'Invalid UTC-offset.']
348 i@(Instant traits) rationalise
349 "Adjust the receiver so localTime is less than a day and positive."
350 [| timeDays |
351   i localTime isNegative ifTrue:
352     [timeDays := i localTime days abs + 1.
353      i localDate := i localDate subtractDays: timeDays.
354      i localTime := (Duration days: timeDays) + i localTime].
355   "Ensure time is less than a day."
356   (timeDays := i localTime days) > 0 ifTrue:
357     [i localDate := i localDate addDays: timeDays.
358      i localTime := i localTime - (Duration days: timeDays)].
359   i
362 i@(Instant traits) + d@(Duration traits)
363 [i clone `setting: #{#localTime} to: {i localTime + d} `>> [rationalise. ]].
365 i@(Instant traits) - d@(Duration traits)
367   i + d negated
370 i1@(Instant traits) - i2@(Instant traits)
372   "We're expecting Date - Date to give a Duration here."
373   (i2 localDate - i1 localDate) + (i2 localTime - i1 localTime)
376 i@(Instant traits) now
378   i clone `setting: #{#localTime} to: i surroundings ticksSinceEpoch
381 time define: #DaylightEndDate.
382 time define: #DaylightOffset.
383 time define: #DaylightStartDate.
384 time define: #DaylightTimeZoneAbbrev.
385 time define: #DaylightTimeZoneName.
386 time define: #DaysInMonth.
387 time define: #DaysToMonth.
388 time define: #DefaultIsStandard.
389 time define: #Offset.
390 time define: #StandardOffset.
391 time define: #StandardTimeZoneAbbrev.
392 time define: #StandardTimeZoneName.
393 time define: #TimeZoneAbbrev.
394 time define: #TimeZoneName.
396 time define: #TimeZone &slots: {#name. #offset. #abbreviation}.
397 "TimeZone collects basic information to encode a UTC time zone."
399 tz@(TimeZone traits) newNamed: name offset: offset abbrev: abbreviation
401   tz traits define: abbreviation intern ->
402    (tz clone `setting: #{#name. #offset. #abbreviation} to: {name. offset. abbreviation})
405 TimeZone newNamed: 'Universal Time' offset: 0 abbrev: 'UTC'.
406 TimeZone newNamed: 'Greenwich Mean Time' offset: 0 abbrev: 'GMT'.
407 TimeZone newNamed: 'Pacific Standard Time' offset: -8 abbrev: 'PST'.
408 TimeZone newNamed: 'Pacific Daylight Time' offset: -7 abbrev: 'PDT'.
410 n@(Number traits) seconds
411 [Duration newForSeconds: n].
413 n@(Number traits) minutes
414 [Duration newForMinutes: n].
416 n@(Number traits) hours
417 [Duration newForHours: n].
419 n@(Number traits) days
420 [Duration newForDays: n].