Chronos is one of the many Smalltalk-related blogs syndicated on Planet Smalltalk

Discussion of the Essence# programming language, and related issues and technologies.

Blog Timezone: America/Los_Angeles [Winter: -0800 hhmm | Summer: -0700 hhmm] 
Your local time:  


DateAndTime Construction--And Nominal Time Invariance

At the cost of adding a few new (small) methods (in the latest development version of Chronos, B1.20) I've made it much easier to compose a DateAndTime by combining a TimeOfDay with a Date (or with an AnnualDate, or with a DateAndTime.) The new instance methods (of TemporalCoordinate and CalendricalCoordinate, respectively) are #on: and #atTimeOfDay: The new class methods (of Timepoint) are #todayAt: and #todayAt:in:.

Here are some example usages:

DateAndTime todayAt: TimeOfDay now
DateAndTime todayAt: TimeOfDay now in: (Duration hours: 5.5)
TimeOfDay now on: YearMonthDay today
TimeOfDay now on: Timepoint today
(TimeOfDay hour: 17 minute: 30 second: 0) on: (YearMonthDay year: 2006 month: June day: 14)
(TimeOfDay hour: 17 minute: 30 second: 0) on: (DateAndTime year: 2006 month: June day: 14)
(TimeOfDay hour: 9 minute: 20 second: 0) on: GregorianEaster canonical
YearMonthDay today atTimeOfDay: TimeOfDay now
DateAndTime today atTimeOfDay: TimeOfDay now
GregorianEaster canonical atTimeOfDay: (TimeOfDay hour: 12 minute: 0 second: 0)

Which produce the following results when evaluated:


You might notice that some of the Timepoints that result from the examples above show a time zone offset, and some don't. Those that show a time zone offset are invariant to Universal Time. Those that don't are invariant to nominal time. A VisualWorks Timestamp has nominal time invariance. A DateAndTime instance that conforms to the ANSI-Smalltalk Standard has Universal Time invariance. Instances of either java.util.Calendar or of java.util.Date also have Universal Time invariance.

If "(DateAndTime year: 2006 month: 1 day: 1 offset: 0 hours) = (DateAndTime year: 2006 month: 1 day: 1 hour: 8 minute: 0 second: 0 offset: 8 hours)" evaluates to true, then the two DateAndTime instances have Universal Time invariance. For Universal-Time invariant time values, the point in Universal Time they designate is their invariant for the purpose of defining their meaning (semantics)--such as whether or not they are equal to some other point-in-time value.

A time value that is invariant to Universal Time will still designate the same point in Universal Time when it is translated or converted to a different time zone.

A time value that is invariant to nominal time always designates the same nominal time regardless of time zone (in other words, it acts just like a VisualWorks Timestamp.) It uses the nominal time it designates as its semantic invariant. It compares as equal to any time value that designates the same nominal time. When bound to a time zone (converted into a point-in-time that is invariant to Universal Time) its local time in the time to which it has become bound is the same as its former nominal time (because its nominal time is its semantic invariant.)

If you create a Core.Timestamp (or a nominal-time invariant Chronos.Timepoint) in an image running in San Francisco, save the image, take it with you on a plane flight to Bangalore, then restart the image, that Core.Timestamp instance would still designate the same nominal time--because there is no "binding" between a nominal-time-invariant time value and any particular time zone.

I know that most of you have been trying to use Core.Timestamps as though they had Universal Time invariance--because that's usually what you need. But Core.Timestamps do not have Universal Time invariance--which is one of the reasons they sometimes don't work for you the way you'd like.

If you need to deal with time values from multiple time zones, you need point-in-time objects with Universal Time invariance. The ANSI-Smalltalk Standard requires them. Chronos provides them. The VisualWorks Core library does not.

Which is not to say that nominal time invariance doesn't have its uses. It certainly does. The canonical example is dates that are literal values in business rules (such as the rules that define which days are holidays.) And trying to use Universal Time invariant time values in situations where they are not appropriate can lead to even worse problems than using nominal time invariant time values when Universal Time invariance is that's needed. Just ask those who've had to use java.util.Calendar for certain use cases.

Note: The latest "relatively stable" development version of Chronos is always available from the Cincom Public StORE Repository.

No comments: