Most implementations are closed and cannot be easily extended necessitating awkward conversion methods. The support for iterating over a time span between two dates is usually very poor. The result is verbose code, cluttered with arcane conversion methods, which it preoccupied with the details of the date instances. Enumeration constructs are extremely susceptible to errors at or near the iteration boundaries.
This situation should not be tolerated by developers. The Gregorian calendar with years, months, weeks and dates is almost universal and is most certainly the dominant calendar used in commercial software. The developer should reasonably expect to see classes which endorse these concepts.
Most significantly, such temporal classes should provide robust, stable and elegant mechanism to iterate over these temporal classes in a manner consistent with the iteration protocol for that language.
The timing is also superb.
The ANSI specification has been completed which dictates a very usable protocol for representing dates, times and durations. Implementing the DateAndTime and Duration protocols will provide a standard foundation based on UTC.
This implementation can be augmented by additional temporal classes providing the commercial developer with the craven functionality.
The Duration class is interpreted to represent some duration of time possibly negative. DateAndTime instances are interpreted to represent a point in Universal Co-ordinated Time space. By definition they have zero duration.
Moore's Law is accepted to hold, so the implementation will have nanosecond precision. This is fully UTC compliant and provides the high precision needed for database timestamps and GUI events. This decision should help minimize the need for a further class library to be developed.
To support the new temporal library, we introduce the concept of a Timespan which spans UTC time for a specified duration starting from some arbitrary DateAndTime. This information is sufficient to determine the end time of the duration. The timespan is designed to be similar to the Interval class although its elements are interpreted to be a continuous collection of DateAndTime instances.
This concept is further promoted by introducing classes for familiar the timespans of Years, Months, Weeks and individual dates.
We note that the introduction of the DateAndTime class as the preferred representation of time, frees up the Date class for redeployment. The notion of a date 'Date' is familiar to all people and represents a full day, midnight to midnight, 24 hours, a full 86400 seconds. We leverage this and reuse Date and a new subclass of Timespan. The existing Time class is inserted as a subclass of DateAndTime for compatibility. Its role in the new library is still not fully known.
Object Duration DateAndTime Time
Object Timespan Year Month Week Date
The timespan classes re-implement much of the ANSI DateAndTime protocol to reduce unnecessary conversion.
Duration zero.
Duration seconds: 90060.
123 asDuration.
DateAndTime now.
DateAndTime year: 2000 month: 8 day: 17 hour: 16 minute: 34 second: 40.
DateAndTime now asDate.Date today.d := Date year: 2000 month: 5 day: 28. d start. d end. d duration. d end - d start. d dayOfWeekName.
Week startDay.Week current.DateAndTime now asWeek.Date today asWeek.Week current dates.Week current datesDo: [ :d | Transcript cr; show: d ].Week current workDatesDo: [ :d | Transcript cr; show: d dayOfWeekName ].
Month current.DateAndTime now asMonth.Month current weeks.Month current dates.
Year current.Year year: 2000.Date today asYear.Month current asYear.Year months.
financialYear := Year starting: (Date year: 2001 month: 4 day: 1). "e.g.. 1 April 2001" financialYear start. financialYear end."Produce a report..."Transcript clear. aStream := Transcript. aStream cr; nextPutAll: 'Report. Financial Year Ending: '. financialYear end asDate printOn: aStream. aStream cr; nextPutAll: (String new: 60 withAll: $-).financialYear monthsDo: [ :aMonth | | workDays | aStream cr. aMonth printOn: aStream. aStream crtab; nextPutAll: aMonth weeks size printString; nextPutAll: ' weeks'.workDays := 0. aMonth workDatesDo: [ :d | workDays := workDays + 1 ]. aStream crtab; nextPutAll: workDays printString; nextPutAll: ' work days'. ].aStream flush.
Other applications need to iterate over a timespan in unusual intervals. Consider the code necessary to inspect a timespan of one second every millisecond:jail := Timespan starting: (Year year: 2000) start ending: (2010 asYear). jail years. jail yearsDo: [:y | Transcript cr; show: y asDate]
oneSecond := Timespan starting: DateAndTime now duration: (Duration seconds: 1). millisecond := Duration nanoSeconds: 1000000. x := 0. oneSecond every: millisecond do: [ :t | x := x + 1 ]. x printString.
Test pilots would be most appreciated. The development effort has focussed on making the programming interface elegant and intuitive. Performance does not appears to be a problem and may be improved if needs be. The DateAndTime protocol is almost complete.