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:  


Physicists Predict Stock Market Crashes

Physicists Predict Stock Market Crashes from

On Monday, October 19, 1987 – infamously known as “black Monday” – the Dow fell 508 points, or 22.9%, marking the largest crash in history. Using an analytical approach similar to the one applied to explore heart rate, physicists have discovered some unusual events preceding the crash. These findings may help economists in risk analysis and in predicting inevitable future crashes.

See also:


Preliminary Port of Chronos To Squeak Published

Avi Bryant has published a very preliminay (and only partially functional) port of Chronos to Squeak. It's available from SqueakSource or from Squeak Map. It is very much a "work in progress." When Avi is satisfied that the port is sufficiently functional and stable, he will make a general announcement to that effect. No promises have been made with respect to when a version suitable for general use may become available, nor is there any commitment to provide all the same functionality as is available from the VisualWorks version. Of course, nothing prevents others from contributing improvements/enhancements in addition to whatever Avi publishes (hint, hint.)

I am very appreciative of the contributution Avi is making towards porting Chronos to Squeak.

Fair warning: As of Mon, 27 Feb 2006 01:39:04 +0000 (Universal Time,) the version on SqueakMap will not work "as is" in versions of Squeak from 3.7 onward (you can load it, but if you execute the initialization/installation "do it" that the pop-up Transcript window suggests, you will then be unable to either save the image or compile any methods.) The problem is caused by the fact that the installation procedure (as implemented in the version currently available from SqueakMap) redefines both DateAndTime and Duration so that they are aliases for the Chronos classes Timepoint and ScientificDuration (respectively,) in place of the native Chronology classes named DateAndTime and Duration (and this issue is precisely why I chose not to use the names "DateAndTime" and "Duration" as class names.) This problem can be fixed if you install Chronos according to the following procedure:

  1. Download the Chronos Update for Squeak (based on Chronos Version B1.64).

  2. Extract the files Chronos-B1.64.1.cs and Chronos-Squeak.cs from the zip archive downloaded in step 1.
  3. File in both of the changeset (*.cs) files extracted in step 2 (this assumes you have already installed Chronos from the version on SqueakSource/SqueakMap.) The file Chronos-B1.64.1.cs contains all the platform-independent Chronos code, less some of the initialization/installation logic. The file Chronos-Squeak.cs contains deltas to the Squeak-specific code provided by Avi that substantially improve the functionality of Chronos on Squeak (but it does not enable accessing any time zones from the Chronos Time Zone Repository.)
  4. Evaluate the following expression in a workspace:

    at: #Duration put: ScientificDuration;
    at: #DateAndTime put: Timepoint.

    If this is not done, many of the code examples in the method comments won't work, because they expect DateAndTime and Duration to be references to Chronos.Timepoint and Chronos.ScientificDuration. Since all the Chronos classes have the global Chronos as a shared pool Dictionary, the above code makes the Browsers bind #DateAndTime and #Duration to their Chronos implementations when browsing a Chronos class. If you'd also like to achieve the same effect in any of your own classes, just add #Chronos and #ChronosConstants as pool Dictionaries.

  5. Now evaluate "ChronosEnvironment install." (But dont't do so until until the above steps have been completed.)

Avi is using Squeak 3.6 to do the porting work. The Chronology library did not become part of standard Squeak until version 3.7, and so there is no issue raised by (re)defining the globals DateAndTime and Duration as global aliases for Timepoint and ScientificDuration (respectively) in versions of Squeak prior to 3.7. That may well be why Avi is using Squeak 3.6 to do the port. (Squeak badly needs a mechanism to more elegantly handle issues such as this one.)

Note that the version currently available from SqueakMap has not been given the ability to access files--so it can't retrieve any time zones from the Chronos Time Zone Repository, and therefore Olson time zone keys such as 'Americal/Los_Angeles', 'Europe/Paris' and 'Asia/Tokyo' cannot be used to identify a time zone. Nor is there any code that makes any attempt to determine the local time zone from the host operating system, nor any code that provides any locale information.

Consequently, the Chronos system time zone simply defaults to Universal Time (which is what the native Chronology library does also, so at least you're no worse off than you were before.) Nevertheless, you can still do quite a bit. For example, after loading and properly initializing Chronos, you can evaluate the following expression to set the Chronos system time zone so that it matches the zone rules that have been in effect since 1996 for CET/CEST (Central European Time):

key: #'Europe/Berlin' name: #'Central European Time'
initialOffset: (ScientificDuration hours: 1) withAbbreviation: #CET
until: (WeekOfMonthDayOfWeek month: 3 week: 0 dayOfWeek: 1)
"The 'zeroeth week' means the last week of the month"
at: (TimeOfDay hour: 1 minute: 0 second: 0) relativity: #universal
thenOffset: (ScientificDuration hours: 2) withAbbreviation: #CEST
until: (WeekOfMonthDayOfWeek month: 10 week: 0 dayOfWeek: 1)
at: (TimeOfDay hour: 1 minute: 0 second: 0) relativity: #universal)

Then, you can evaluate "Timepoint now" to see the current time. And if you find yourself in Madrid, Paris, Berlin or Amsterdam, the answer will even be correct. However, due to the fact that the Squeak system clock reports local time, setting the Chronos system time zone has no effect on what is displayed when "Timepoint now" is evaluated. It only changes the results of evaluating "Timepoint utNow." On a system whose clock reported Universal Time, the situation would be reversed.


Version 2006b of the Chronos Time Zone Repository Published

Arthur David Olson has published version 2006b of the Olson Time Zone Database. Consequently, version 2006b of the Chronos Time Zone Repository has been generated from the new version of the Olson TZDB, and is available from the Chronos web site.

Chronos Version B1.60 Published

Version B1.60 of the Chronos Date/Time Library has been published. It's available from the Chronos web site, or from the Cincom Public StORE Repository. You will also need to obtain and install the Chronos Time Zone Repository according to the Chronos Installation Instructions, if you have not done so previously.

Version B1.60 mostly includes changes and additions to address issues that have arisen in porting Chronos to non-VisualWorks Smalltalk implementations. It also includes some minor and/or obscure bug fixes.

Note also that the URLs for dowloading both the Chronos archive and the Chronos Time Zone Repository archive have changed. The new URLs are as follows:

The Chronos codebase is now also available in a file-out format that should be directly consumable by non-VisualWorks Smalltalk platforms. VisualWorks refers to this format as the "VW3.0" format. It should be completely compatible with the original "Blue Book" file-out format, and I have verified that it is consumable by Squeak, Dolphin and Smalltalk/X.

The "platform-neutral" version of the Chronos distribution is called the "Chronos Seed." You can obtain the latest Chronos Seed Archive from

The files in the "Chronos Seed" archive are as follows:

  1. The platform-independent code of Chronos. Chronos will not be functional with only this code installed. To make a functional version of Chronos, you must do the tasks specified in the Chronos Porting Instructions, and you must file-in Chronos-Class and (but see the comments below before doing that!)

  2. Chronos-Class Class initializaion methods, and "do its" that execute them on file-in. This code is necessary, but you will need to avoid execution of the "do its" unless and until your port is sufficiently functional.

  3. Code that causes Chronos to fully initialize and install itself on file-in. You must avoid execution of this code until your port is sufficiently functional.

  4. Useful extensions to base VisualWorks classes. Optional--and this file is specific to VisualWorks. However, it is probably a good idea to add analogous extensions to the target Smalltalk environment (although that is not at all required.)

  5. Chronos-ST80 (and VW) Adds methods to various Chronos classes so that they will be type-compatible with the VisualWorks Date, Time and Timestamp classes. Optional--and this file is specific to VisualWorks. However, you may want to add methods to Chronos so that some of the Chronos classes will be type-compatible with the native Date/Time classes of the target platform.

  6. Contains the code for the Chronos Time Zone Compiler. Optional--and hopefully, not VisualWorks specific.


Sci/Tech: Scientists develop better method for converting sounds to electronic signals

Scientists develop better method for converting sounds to electronic signals from

Inspired by the way sound is processed in the brain, researchers at Carnegie Mellon University (CMU) have devised a new, highly efficient scheme for converting sounds to digital form. The payoff could be a significant improvement in the sound quality of cochlear implants, digital audio players, cellular telephones and many other devices.

Sci/Tech: Computer chips can get smaller, cheaper than first thought: IBM researchers

Computer chips can get smaller, cheaper than first thought: IBM researchers from

Researchers at IBM have discovered that current chip-making technology has the potential to make computer processors even tinier and cheaper than was first thought.

So Moore's Law gets yet another reprieve. And once lithographic techniques finally meet their limits, there are other technologies waiting their chance to play the game.


Sci/Tech: Quantum telecloning: Captain Kirk's clone and the eavesdropper

Quantum telecloning: Captain Kirk's clone and the eavesdropper from

Imagine Captain Kirk being beamed back to the Starship Enterprise and two versions of the Star Trek hero arriving in the spacecraft's transporter room. It happened 40 years ago in an episode of the TV science fiction classic, and now scientists at the University of York and colleagues in Japan have managed something strikingly similar in the laboratory - though no starship commander was involved.

Einstein Equations

Einstein Equations from

Throughout the years mathematicians and physicists have been finding various solutions to Einstein’s equations. These solutions have helped scientists better understand the nature of our cosmos, as well develop theories about the relationships between space and time. Now two physicists at the University of Waterloo in Waterloo, Ontario, Canada, have developed a new family of solutions to Einstein’s equations — in five dimensions.

Sci/Tech: Quantum computer solves problem, without running

Quantum computer solves problem, without running from

By combining quantum computation and quantum interrogation, scientists at the University of Illinois at Urbana-Champaign have found an exotic way of determining an answer to an algorithm – without ever running the algorithm.


Sci/Tech: New material means 'x-ray specs' no longer required

New material means 'x-ray specs' no longer required from

A new optical effect has been created in a London laboratory that means solid objects such as walls could one day be rendered transparent, scientists report today in the journal Nature Materials.


Chronos Version B1.55 Published; Date/Time Parsing Now Supported

Version B1.55 of Chronos has been published. It's available from the Chronos web site, or from the Cincom Public StORE Repository.

Unless you have installed Chronos before, you will also need to download and install the Chronos Time Zone Repository, as detailed in the Chronos Installation Instructions.

What's new and/or changed in Chronos version B1.55

Firstly, the major change is that date/time parsing has beem implemented! More on that below.

Secondly, the administrivia and minor changes:

  • Bundle/Package reorganization:

    • Moved Chronos-Timescales, Chronos-Calendars and Chronos-TimeZones from the bundle Chronos to the bundle Chronos-Kernel.

    • Created the Bundle Chronos-Platform-Abstraction under Chronos, and moved the packages Chronos-Environment and Chronos-System from Chronos-Kernel to Chronos-Platform-Abstraction. So Chronos-Kernel now contains Chronos-Foundation, Chronos-Timescales, Chronos-Calendars and Chronos-TimeZones (all the classes that constitute the underlying date/time "engine" that enables Chronos to do what it does--stuff that casual users of the Chronos codebase wouldn't normally need to be concerned with.)

    • Renamed the package Chronos-Calendars-Kernel to Chronos-Calendars-Foundation (for consistency with Chronos-Kernel and Chronos-Foundation.)

    • Renamed the package Chronos-Calendars-Arithmetical to Chronos-Calendars-Regular, and renamed the class ArithmeticalCalendar to RegularCalendar (to better reflect the intent and implementation.)

    • Renamed the package Chronos-Calendars-Astronomical to Chronos-Calendars-Irregular, and renamed the class AstronomicalCalendar to IrregularCalendar (to better reflect the intent and implementation.)

    • Created the package Chronos-Parsing under Chronos (more on that below.)

    • Created the bundle Chronos-Platform Extensions under Chronos, and moved the packages Chronos-ST80 (and VW) Compatibility and Chronos-VW-Extensions there from the bundle Chronos.

    • Created the bundle Chronos-Load under Chronos, and moved the packages Chronos-Class Initialization and Chronos-Installation there from Chronos.

  • Moved the following methods to the package "Chronos-Class Initialization" (as extension methods):

    • ChronosEnvironment class>>setPlatformClass

    • CalendarDuration class>>initialize

    • ChronosLocale class>>initialize

    • ScientificDuration class>>initialize

  • Moved all the methods in TimeOfDay's 'ST80/VW compatiblity' protocol to the "Chronos-ST80 (and VW) Compatibility" package.

  • Renamed #printCalendarDuration:on: to #printCivilDuration:on: (to better reflect the actual behavior.)

  • Changed the method ChronosEnvironment class>>preInstall so that it is a no-op if a) ChronosEnvironment has no subclasses, or b) there is a global defined whose name is ChronosInstallationFlag and whose value is false. The purpose is both to aid porting out of VW and also as a failsafe mechanism for installing the Chronos code in cases where the installation/initialization logic is broken (for whatever reason.)

Date/Time Parsing

The classes ChronosParser and ConfigurableChronosParser have been added, in the new package Chronos-Parsing. ChronosParser is an abstract class; ConfigurableChronosParser is a concrete subclass of ChronosParser. ChronosParser defines the API.

ConfigurableChronosParser is implemented to be very flexible and forgiving, as opposed to being very rigid and strict. Those who require rigid/strict parsing, or for whom ConfigurableChronosParser is not suitable (for whatever reason,) have the option of defining their own subclass of ChronosParser to suit their specific requirements (perhaps using SmaCC to generate the parsing logic.)

One unavoidable consequence of the forgiving, flexible behavior of ConfigurableChronosParser is that it cannot claim to be the fastest date/time parser available. However, it should be more than adequate for use in UIs, for casual use, or to quickly get up and running (First make it work, then make it fast.)

A ConfigurableChronosParser will try its best to interpret the date/time as a human would. It handles two-digit years, "am" and "pm," time zone names, time zone abbreviations, time zone offsets, multiple locales and multiple calendars. With a few exceptions, it doesn't care about separators--including no separators at all. If no valid interpretation of the data can be inferred with strong certainty, an exception is thrown.

The following configuration messages can be sent to a (mutable) instance of ConfigurableChronosParser:

  • setDefaultTimeZone: (used only if no time zone is explicitly specified from the parsed data)

  • setLocale: (each instance is specific to a particular locale)

  • setCalendar: (each instance is specific to a particular calendar)
  • setTwoDigitYearBackwardBias: (to set the number of years back from the current year for which the parser will assume that the 2 least significant digits of such years correspond to those of a given two-digit-year)

  • interpretMonthNumberAsNumericDesignator (for Hebrew dates using the religious month numbering convention)

  • interpretMonthNumberAsOrdinal (for Hebrew dates using the secular month numbering convention)

  • doNotExpectDayOfWeekName (default)

  • expectDayOfWeekName (so that RFC 2822 can be parsed)

  • expectDMY (makes the parser resolve any ambiguities in favor of a day-month-year ordering of the elements of a date)

  • expectMDY (makes the parser resolve any ambiguities in favor of a month-day-year ordering of the elements of a date)

  • expectYDM (makes the parser resolve any ambiguities in favor of a year-day-month ordering of the elements of a date)

  • expectYMD (makes the parser resolve any ambiguities in favor of a year-month-day ordering of the elements of a date)

Here are some executable examples of what a ConfigurableChronosParser can do:

ChronosParser default nextDateFrom: 'February 16, 2006'readStream
DateAndTime readFromString: '1976-07-04T17:00 EDT'
DateAndTime readFromString: '1976-07-04T12:00 am EDT'
DateAndTime readFromString: '1976-07-04T12:00 pm MST'
'1776-07-04' asDateAndTimeUsing: #iso8601
" ^-- Default time zone is Universal Time--as required by IS0 8601,
RFC 2822, WS-I Basic Profile 1.0, and various other standards."
'1776-07-04' asDateAndTimeUsing: #ansiStandard
" ^-- Default time zone is system local time--which is how most
time-zone-enabled applications operate."
'1776-07-04' asDateAndTimeUsing: #default
" ^-- Default time zone is nominal time--which is how most VisualWorks
and Squeak applications actually operate--even though most think otherwise."

'20040229' asDateAndTimeUsing: #iso8601
'2004-060' asDateAndTimeUsing: #iso8601
'2004060' asDateAndTimeUsing: #iso8601
'2004-W09-7' asDateAndTimeUsing: #iso8601
'2004W097' asDateAndTimeUsing: #iso8601
'7/4/76-07:00' asDateAndTimeUsing: #mdy
'7/4/1776+10:30' asDateAndTimeUsing: #mdy
'4 July 1776-04' asDateAndTimeUsing: #dmy
'04-JUL-1776Z' asDateAndTimeUsing: #dmy
'1776-07-04T09:22:12 America/New_York' asDateAndTimeUsing: #iso8601
'Thu, 04 Jul 1776 19:15:00 -0500' asDateAndTimeUsing: #rfc2822
'7/4/76 at 9:22:12 pm MDT' asDateAndTimeUsing: #mdy
'4 July ''76 9:22:12 pm MDT' asDateAndTimeUsing: #mdy
'9:22:12 am 7/4/76 MST' asDateAndTimeUsing: #(expectTimeThenDate expectMDY)
'Thursday, July 4, 1776 @ 7:15 pm +0530' asDateAndTimeUsing:
#(#expectDayOfWeekName #expectMDY)
'4 juillet 1776 7h15' asDateAndTimeUsing:
#(expectDMY setLocale: #fr_FR setDefaultTimeZone: 'Europe/Paris')
('5536 Tammuz 17, 07:15' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765 Adar Rishon 14, 18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765 Adar Sheni 14, 18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765 Adar 14, 18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765-13-14T18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew
setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765-07-14T18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString


Physicist to Present New Exact Solution of Einstein's Gravitational Field Equation

Physicist to Present New Exact Solution of Einstein's Gravitational Field Equation from

New antigravity solution will enable space travel near speed of light by the end of this century, he predicts.

On Tuesday, Feb. 14, noted physicist Dr. Franklin Felber will present his new exact solution of Einstein's 90-year-old gravitational field equation to the Space Technology and Applications International Forum (STAIF) in Albuquerque. The solution is the first that accounts for masses moving near the speed of light.


Chronos Version B1.32 Published

The new version is available from the Chronos web site, or from the Cincom Public StORE Repository. If you have never installed Chronos before, you'll also need the Chronos Time Zone Repository.

Changes in version B1.32:

1. Created a new package named Chronos-Semantic Dates; moved all code relating to SemanticDates (e.g., holidays) to this package.
2. Added ChronosUtility class>>isNilOrEmpty:
3. Changed the various senders of "x size", where the receiver ("x") was intended to sometimes be nil, to use "ChronosUtility isNilOrEmpty: x" instead.
Reason: Not all Smalltalk environments implement nil so that it answers 0 in response to the message #size.

4. Fixed bug in SemanticDatePolicy class>>usFederalHolidaySemanticKeys (there was a typo: WashingtonsBirthDay => WashingtonsBirthday)

5. Fixed minor bug in the example method AnnualDate class>>showSelectedJewishHolidaysForThisYearAndNextYear

Chronos/VisualWorks Compatibility

A lot of work has been put into type-compatibility and interoperability between the Chronos objects that represent dates, times-of-day and date-and-time values and the analogous objects natively present in VisualWorks.

Firstly, instances of Chronos.ChronosTimezone (aliased by Smalltalk.Timezone,) Chronos.TimeOfDay, Chronos.YearMonthDay and Chronos.Timepoint (aliased by Smalltalk.DateAndTime) all respond to the message #asNative with a conversion of themselves into an equivalent instance of Core.TimeZone, Core.Time, Core.Date or Core.Timestamp (respectively.)

If one were using a version of Chronos hosted in some Smalltalk environment other than VisualWorks, the #asNative message would result in an equivalent instance of whatever class is natively used in that environment to represent the same value as is represented by the Chronos object that receives the message #asNative.

Of course, such conversions may lose information, since the Chronos objects have more semantic content that do the equivalent objects native to either VisualWorks or to any of the other Smalltalk environments.

Secondly, instances of Core.TimeZone, Core.Time, Core.Date and Core.Timestamp respond to the message #asChronosValue with a conversion of themselves into an equivalent instance of Chronos.ChronosTimezone, Chronos.TimeOfDay, Chronos.YearMonthDay or Chronos.Timepoint (respectively.)

Conversion from native date/time objects to the equivalent Chronos objects are semantically lossless. For example, when #asChronosValue is sent to a Core.Timestamp, the response is a Chronos.Timepoint that is not bound to any particular time zone, and is therefore invariant to nominal time--which is precisely the semantics of a Core.Timestamp.

Additionally, Core.Time, Core.Date and Core.Timestamp all provide additional protocol for converting themselves into analogous Chronos objects:

  • #as: -- Answers the conversion of the receiver into either a Chronos.YearMonthDay or a Chronos.Timepoint (depending on whether the receiver is or is not an instance of Core.Date) that represents the same absolute date (and time-of-day, if applicable) as the receiver, but represented according to the calendar specified by the argument

  • #asDateAndTime -- Answers the conversion of the receiver into a Chronos.Timepoint that represents the same local date and time-of-day as the receiver in the current default Chronos time zone; the answered Timepoint will have Universal-Time-invariant semantics

  • #asNominalDateAndTime -- Answers the conversion of the receiver into a Chronos.Timepoint that represents the same nominal date and time-of-day as the receiver; the answered Timepoint will have nominal-time-invariant semantics

  • #in: -- Answers the conversion of the receiver into a Chronos.Timepoint that represents the same local date and time-of-day as the receiver in the the Chronos time zone specified by the argument; the answered Timepoint will have Universal-Time-invariant semantics, unless the argument is <ChronosTimezone nominal>

Chronos.TimeOfDay, Chronos.YearMonthDay and Chronos.Timepoint also respond to the same four messages, with the same semantics.

Thirdly, for almost every instance and class method defined in the inheritance hierarchy of Core.Date there is a corresponding method with the same selector in the inheritance hierarchy of Chronos.YearMonthDay, and for almost every instance and classs method defined in the inheritance hierarchy of Core.Timestamp there is a corresponding method with the same selector in the inheritance hierarchy of Chronos.Timepoint. And all such methods have the same semantics. There are a few exceptions--but almost all of those are private methods (although even some of those are included.)

For example, the following statements/expressions will all work correctly:

YearMonthDay newDay: 1461 year: 2000

YearMonthDay fromDays: Date today asDays

YearMonthDay today subtractDate: Date today

Date today subtractDate: YearMonthDay today

YearMonthDay today previous: #Saturday

Timepoint fromDate: Date today andTime: Time now

Timepoint fromSeconds: Timestamp now asSeconds

YearMonthDay today printFormat: #(1 2 3 $- 2 2)

Locale current printAsTime: Timepoint now policyNamed: #long

YearMonthDay readFromString: Date today printString

(Timezone at: 'Australia/Adelaide')
convertGMT: Time secondClock
do: [:date :seconds |
with: date
with: (Time fromSeconds: seconds)]

ChronosTimezone default
convertToGMT: Timestamp now asSeconds
do: [:date :seconds |
with: date
with: (Time fromSeconds: seconds)]


Chronos Version B1.29 Published

Someone is porting Chronos from VisualWorks to a different flavor of Smalltalk. No mention was made as to when, nor even whether, this particular Chronos port might become publicly available--and no, I won't tell you who's doing it, nor even what the target Smalltalk environment happens to be, so you'll just have to wait until the party in question decides to make an announcement. And no, I'm not the one.

What I will say is this: A first cut at the port was completed without any aid or advice from me. I only found out about it when I got an e-mail detailing the problems that arose and the steps necessary to overcome them. I believe the party in question is waiting for this new version so that "they" (to be mysterious) can synchronize their port with it before proceding to package up the ported version and put a bow on it.

Many of the changes in this version are motivated by the porting issues discovered during the Chronos port mentioned above:

1. New package created: Chronos-Class Initialization.

Moved certain class-side #initialize methods from the "home" package of their class to the Chronos-Class Initialization package (as "extension" methods.) Reason: To address portability issues discovered during the Chronos port mentioned above. There's a new version of the Porting.html document that discusses this issue (and also other new issues.)

2. Added the methods ChronosUtility class>>ansiValueOfLiteralArrayElement: and ChronosUtility class>>ansiValueOfArrayLiteral:. The first method converts #nil to nil, #true to true and #false to false, but leaves all other values unchanged, and the second method applies the first to the contents of its argument (which should be an Array literal.)

3. Made the Chronos code agnostic with respect to whether or not the compiler of the host Smalltalk environment interprets Array literals according to the ANSI Standard (where #(nil) = (Array with: nil)) or according to the original "Blue Book" (where #(nil) = (Array with: #nil).)

So in VW, both "Timepoint now printStringUSing: #(timeZoneElementSeparator: nil)" and "Timepoint now printStringUSing: #(timeZoneElementSeparator: #nil)" will work the same, and neither will be an error.

4. Delagated responsibility to the ChronosEnvironment for constructing a character value to represent the euro currency symbol. If the host Smalltalk environment can't represent that character, then it can't, and Chronos will simply use a different default currency symbol (i.e., $, which is not the default in VW.)

5. Converted all the Bahai Calendar month-name Symbol literals to "quoted" syntax. For instance, #Bahá => #'Bahá'

6. Added the instance methods #makeMutable: and #makeImmutable: to ChronosSystemFacade. Changed all (other) senders in the Chronos codebase of the VW-specific #isImmutable: message to instead use #makeMutable: or #makeImmutable:.

7. Added binary operator % to ChronosPrintable. It takes any of 1) a ChronosPrintPolicy, 2) a key of a registered ChronosPrintPolicy (string or symbol), or 3) a ChronosPrintPolicy spec array as its argument, and answers the result of sending #printStringUsing: (with the same argument) to the receiver.


Timepoint now % #rfc2822
=> ''Sun, 05 Feb 2006 23:04:36 -0800''
Timepoint now % (ChronosPrintPolicy applying: #(timeOfDayPrefix: $@))
=> ''2006-02-05@23:05:53.528256-08:00''
Timepoint now % #(timeOfDayPrefix: $@)
=> ''2006-02-05@23:06:46.506399-08:00''

For information on the prior release, see the Chronos Version B1.25 Publication Announcement. That announcement has a link to the information about yet earlier released versions.


Why Can’t The Windows Registry Timezones be used?

A poster with the handle iwonder started a thread on the forum, titled On Time Zones and Daylight Saving Time (Summer Time).. (I've added the whole thread to the "Cautionary Tales" section of the Chronos web site.) In a subsequent post to the thread, he has a subsection titled "Why Can’t The Windows Registry Timezones be used?", where he states:

First, and foremost the 75 windows registry timezones only are setup to support current year. Meaning that there is no historical reference. In fact, when a given locale changes their time zone daylight saving (summer time) rules, these rules need to be manually ‘fixed’ in the registry. These types of corrections are not distributed by Microsoft as updates to anyone. The corrections appear in KB articles, but the corrections could easily be missed by folks that are not in the locale affected. As each year starts, new rules are in place, which may not calculate the correct date time adjustments for any past years. Actually, any date time adjustment based on the registry alone results in a date time factored with the current years’ rules. Not exactly the result time sensitive sites would require.

Secondly, the windows registry is not totally accurate. Independent tests show it to be around 75-80% accurate at any point in time. Also, the time zones do not represent every time zone on the globe, just the more commonly used zones are included. The UNIX / Linux TZInfo database includes many more time zone descriptions, but there is a question of just how many require support. Obviously, MS made the determination that only 75 of the more than 108 zones in the TZInfo database really require support. It’s a question of judgement.

Lastly, web applications are not really meant to have access to the windows registry. It’s really a question of security, but I can’t imagine any host provider wanting to allow a web application to manipulate the registry. In fact, I’m not sure if the Code Access Security model will even allow the type of registry read and write permission required to effectively use and maintain a registry timezone information.

Correct answers in date/time computations are just as important as correct answers in issuing payroll checks, crediting interest earned, sending out invoices, computing work schedules, sheduling airline flights, administering the right medications to the right patients at the right time, getting a spaceship, rocket or missile to its intended destination at the right time, or even just dividing one number by another.

When I hear people say otherwise, there's no doubt in my mind that what I'm really hearing is an emotional reaction against the unwanted complexity of the date/time domain. But neither reality nor complexity goes away just because you wish things were otherwise.

Time is complex. Deal with it. The Universe doesn't care about your preferences, and will happily bite you in a private part of your anatomy if you can't bring yourself to accept and handle the world as it is.


Chronos Version B1.25 Published

Version B1.25 fixes a few bugs and erroneous comments, and adds a few convenvience/syntactic sugar methods:

Added new binary operators .#>> #<< #@ #/ #\


Timepoint now >> 'Australia/Adelaide'
-- same as Timepoint now in: 'Australia/Adelaide'
=> 2006-02-03T16:33:28.610687+10:30
Timepoint nominalNow >> 'Australia/Adelaide'
-- same as Timepoint nominalNow in: 'Australia/Adelaide'
=> 2006-02-02T22:03:38.14332+10:30
Timepoint now << 'Australia/Adelaide'
-- same as Timepoint now asInvariantToNominalTime in: 'Australia/Adelaide'
=> 2006-02-02T22:03:47.792136+10:30
Timepoint nominalNow << 'Australia/Adelaide'
-- same as Timepoint nominalNow asInvariantToUT in: 'Australia/Adelaide'
=> 2006-02-03T16:34:00.088264+10:30
(YearMonthDay year: 1969 month: July day: 20) @ (TimeOfDay hour: 5 minute: 17 second: 40)
-- same as (YearMonthDay year: 1969 month: July day: 20) atTimeOfDay: (TimeOfDay hour: 5 minute: 17 second: 40)
=> 1969-07-20T05:17:40
YearMonthDay today / YearMonthDay tomorrow
-- same as Timeperiod from: YearMonthDay today to:YearMonthDay tomorrow
=> 2006-02-02/P1D
YearMonthDay today / 3 months
-- same as Timeperiod from: YearMonthDay today duration: 3 months
=> 2006-02-02/P3M
YearMonthDay today \ #Hebrew
-- same as YearMonthDay today as: #Hebrew
=> 5766-05-04 [Hebrew]
Added class methods Timepoint class>todayAt: and Timepoint class>todayAt:in:

Timepoint todayAt: (TimeOfDay hour: 13 minute: 30 second: 0)
=> 2006-02-02T13:30:00-08:00

Timepoint todayAt: (TimeOfDay hour: 13 minute: 30 second: 0) in: 'Europe/Berlin'
=> 2006-02-02T13:30:00+01:00
Added CalendricalCoordinate>>atTimeOfDay:in: and TemporalCoordinate>>on:in:

(YearMonthDay year: 2005 month: 12 day: 31) atTimeOfDay: (TimeOfDay hour: 15 minute: 59 second: 59) in: 'America/Los_Angeles'
=> 2005-12-31T15:59:59-08:00

(TimeOfDay hour: 15 minute: 59 second: 59) on: (YearMonthDay year: 2005 month: 12 day: 31) in: 'America/Los_Angeles'
=> 2005-12-31T15:59:59-08:00
Added TemporalCoordinate>>asTimeperiodStartingAt: (with the same semantics as in Durational.)


YearMonthDay tomorrow asTimeperiodStartingAt: YearMonthDay yesterday
=> 2006-02-01/P2D
CalendricalCoordinate>>inYear: (for polymorphism with AnnualDate)--implementation uses #yearOrdinal.
Changed several occurrences here and there of "self calendar yearNumberingPolicy ordinalFromCanonical: year" to "self yearOrdinal" (note: #year does not necessarily answer an ordinal year number--whether #year is an ordinal or cardinal number depends on the Calendar.)

Reimplemented #yearsSinceEpoch using #yearCardinal.

Added ability to print the era name ("AD," "BC") either before or after the date.

Link to information on previous releases:

Discovering the Local Time Zone--Why It's a Hard Problem

I've written a rather long essay that explores all the issues involved in having VisualWorks (and Squeak) synch up with the host operating system's time zone offset rules. It's too long for the blog, so here's the first 3 paragraphs, followed by a link to the full essay:

Smalltalk-80 was released to the world in 1983. I no longer remember exactly when, but well before 1990, ParcPlace systems (the company formed by Xerox to commercialize Smalltalk) introduced a Time Zone class (which had not been in the version given to Tektronix, HP, TI and Apple in 1980--which is why Squeak Smalltalk, which descends from the version Xerox gave Apple, didn't have a Time Zone class until just recently.) It's been roughly 20 years since Smalltalk first had a Time Zone class--well before any other language that I know of had one. And yet both VisualWorks and Squeak, the two modern descendants of Smalltalk-80, still can't configure their Time Zone objects so that the offset transition rules match those of the host operating system (although Squeak dodges the issue by having the VM report clock ticks in local time, an approach that gives the strong but deceptive illusion of "working" as long as one only ever deals with one time zone, and doesn't care about correct time computations into the past or the future.)

Why does this situation persist? Why doesn't Cincom (current ownwers of VisualWorks, which descends from the original ST-80 marketed by ParcPlace) just write a few lines of code so that when VisualWorks first starts up, it finds out what time zone it's in from the host operating environment? Why don't the Squeak folks do likewise? Is this a hard problem or something?

Well, yes. It is. Here's the story, in all its sordid details: Discovering the Local Time Zone--Why It's a Hard Problem.


Martin Fowler talks about TimePoints

Martin Fowler:

The most common issue with time points is that they come at various levels of precision. When I say I'm writing this on August 28 2000, and I say I'm writing this at August 28 2000 2:33:34 pm, I'm saying two different things. One statement is to day precision, and other to second precision. Notice that the second precision is more precise than the day precision, but in this case happens to be less accurate. Any time point needs to know its precision so that you can answer questions such as did this event occur at the same time as another event.

The key point is that you can't rely on only on precision for most domains. Much of business is done at day precision. It doesn't matter when my phone request for transfer of funds occurs during the day, it's just processed according to the day I do it. Otherwise life could get very annoying. If I want to make a transfer the same day a bill is presented for payment, should I worry about exactly what time the bill is presented. Common business practice says no, if it was on the same day, I don't run the risk of going overdrawn or refusing the payment.

Right on! However, the correct technical term when speaking of time is resolution, not precision. Resolution is a matter of the capabilities of the syntax/notation used to represent a temporal value; precision is a matter of data quality. A clock that provides one-microsecond ticks has a resolution of one microsecond--but its precision may not be that high. [Which reminds me: I need to ask Doug Surber what he meant by "DateAndTime clockPrecision" when he put that method in the ANSI Smalltalk Standard's <DateAndTime factory> protocol. I've assumed he actually meant precision, and not resolution.]

Chronos provides YearMonthDay, whose resolution is one civil day, and Timepoint, whose resolution is one nanosecond.

YearMonthDay instances aren't bound to time zones--they have nominal time invariance. Timepoint instances can either be bound to a time zone and have Universal Time invariance, or they can have nominal time invariance and not be bound to any time zone.

As Martin points out, choosing the time-invariance semantics that is right for each situation is of no small importance:
Another tricky area with time points is how to handle time zones. In a similar way with precision, there is no right answer for all applications. Sometimes you'll want a time point with a time zone, sometimes not. A timepoint without a time zone is perfectly sensible, it means within the local time of it's context. You find these where further time zone information is either not useful, or can be obtained from it's context. Be wary of using time zones when you don't need it.

Also be wary of not using time zones when you do need them.

Martin also advises against using temporal intervals as TimePoints. He's absolutely correct. Squeak's Chronology library makes this mistake.

Many other date/time libraries use a model of time that assumes that TimePoints have infinite resolution--which is a different aspect of the same conceptual error (e.g., Joda-Time's concept of the "Instant".) But there is no such thing as infinite resolution--not even in Physics. Such mistakes lead to ugly code, awkward APIs, poor architecture--and perhaps even wrong results.