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:  


Chronos Version B1.3 Published

Bug fix: MNU when attempting to change the system time zone. This bug was introduced very recently. Apparently, there was a mysterious method version regression (an older version of the method became current--I have no idea how that happened.) I fixed it by using StORE to reload the right (later) version of the method (specifically, Core.TimeZone>>initializeFromAnnuallyRecurringTZPolicyFactoryArray:.)

I hope this sort of weirdness doesn't happen often when using StORE.

Watch the leap second as it happens has a Leap Second Countdown Clock where you can watch the leap second happen.

Happy New Year

As I write, it's New Year's Day in Asia:

Sun, 1 Jan 2006 09:54:46 +1300 (NZDT: Pacific/Auckland)
Sun, 1 Jan 2006 07:54:46 +1100 (EST: Australia/Sydney)
Sun, 1 Jan 2006 05:54:46 +0900 (JST: Asia/Tokyo)
Sun, 1 Jan 2006 04:54:46 +0800 (WST: Australia/Perth)
Sun, 1 Jan 2006 04:54:46 +0800 (HKT: Asia/Hong_Kong)
Sun, 1 Jan 2006 02:24:46 +0530 (IST: Asia/Calcutta)
Sat, 31 Dec 2005 23:54:46 +0300 (MSK: Europe/Moscow)
Sat, 31 Dec 2005 22:54:46 +0200 (IST: Asia/Jerusalem)
Sat, 31 Dec 2005 21:54:46 +0100 (CET: Europe/Amsterdam)
Sat, 31 Dec 2005 20:54:46 +0000 (GMT: Europe/London)
Sat, 31 Dec 2005 20:54:46 +0000 (UT: Universal Time)
Sat, 31 Dec 2005 18:54:46 -0200 (BRST: America/Sao_Paulo)
Sat, 31 Dec 2005 17:54:46 -0300 (ART: America/Argentina/Buenos_Aires)
Sat, 31 Dec 2005 15:54:46 -0500 (EST: America/New_York)
Sat, 31 Dec 2005 14:54:46 -0600 (CST: America/Chicago)
Sat, 31 Dec 2005 13:54:46 -0700 (MST: America/Denver)
Sat, 31 Dec 2005 12:54:46 -0800 (PST: America/Los_Angeles)
Sat, 31 Dec 2005 10:54:46 -1000 (HST: Pacific/Honolulu)

Of course, it's only New Year's Day according to the Gregorian Calendar (the official global calendar of business, and the basis of legal time in most countries.) But there are other calendars:

2006-01-01 AD [Gregorian]
0162-16-02 BE [Bahai]
1722-04-23 AM [Coptic]
1998-04-23 ZH [Ethiopic]
5766-10-01 AM [Hebrew]
1927-10-11 AS [Indian Civil]
1426-12-01 AH [Islamic (Fatimid)]
2005-12-19 AD [Julian]
2758-12-19 AUC [Julian (Imperial)]
1384-10-11 AP [Persian]
6242-01-12 SY [Solarian]
2006-001 [Gregorian-ordinal date]
2005-W53-7 [ISO]
J.D. 2453737 [Julian Day]
NewYearsDay weekend (Sunday)


The Leap Second of 2005

The second following 2005-12-31T23:59:59+0000 will be a leap second, and will have the ISO 8601 designation 2005-12-31T23:59:60+0000. In the Universal Time Zone (the one whose offset from the UTC timescale is zero seconds,) the final two seconds of 2005, and the first two seconds of 2006, will be designated as follows:

                                              Seconds since 1970-01-01T00:00:00

Universal Time                  Unix/POSIX Clock     UTC Timescale

2005-12-31T23:59:59            1,136,073,599           1,136,073,621

2005-12-31T23:59:60            1,136,073,599          1,136,073,622

2006-01-01T00:00:00         1,136,073,600          1,136,073,623

2006-01-01T00:00:01          1,136,073,601           1,136,073,624

Firstly, note that leap seconds always occur as the final second of the day in the Universal Time Zone, and therefore occur at some other time of day in any time zone whose offset from UT is not zero. The effect of a leap second is to make the minute that contains it 61 seconds long, the hour that contains it 3601 seconds long, the day that contains it 86401 seconds long, and the year that contains it 31,536,001 seconds long (31,622,401 seconds in a leap year)--all assuming there is only one leap second during those periods, and assuming a positive leap second. Leap seconds can theoretically be negative, although none such have yet to occur.

Where I live in California, the leap second of 2005 will occur as the final second of the final minute before 4pm on Saturday, 31 December 2005 (2005-12-31T15:59:60-8000.)

Secondly, note that the Unix/POSIX system clock does not agree with the count of seconds according to the UTC timescale. The same is true of the Windows and MacOS X system clocks, the VisualWorks system clock, and of the count of seconds returned by an RFC 868 time service (which answers the count of seconds since 1900-01-01T00:00:00+0000.) They all provide answers as though leap seconds didn't exist--although some of them will repeat T59:59:59 twice, so that leap-second-naive algorithms that convert a count of seconds into a year-month-day-hour-minute-second designation will compute the right result.

The reason most system clocks report time (in seconds since an epoch) as though there were always 86400 seconds per day is because most date/time libraries make that assumption. One reason most date/time libraries make that assumption (in addition to the complexity of the code required to handle leap seconds correctly) is because most system clocks report time that way. Specifically, the clock code in the OS kernel converts the date provided by the motherboard's real time clock into a count of seconds based on a naive 86400 seconds/day algorithm, and does not add in a leap second correction. It's a vicious circle.

Of course, most users wouldn't know the difference, and wouldn't care if they did know it. Which is another reason the leap second "catch 22" situation persists to this day, more than 30 years after leap seconds were added to the UTC timescale. Another reason that the situation persists is because most clocks don't keep time to anywhere near one second per year accuracy--and a clock has to be more accurate than even that before leap seconds matter.

Nevertheless, clocks with sufficient accuracy for leap seconds to matter do exist, and will become rather common by the end of the next decade. And there are users and use cases where such accuracy not only matters, but is essential. It is for these reasons that I am working on adding full support for leap seconds into Chronos.

I would like to point out, however, that leap seconds are usually irrelevant in Chronos. The class that implements the "point in time" concept, called Timepoint, does not represent a point-in-time as a count of seconds since an epoch. Instead, it represents a point-in-time as a) a count of days since an epoch and/or a year/day-of-year designation (the same instance may do both,) b) a number of seconds since the start of the day, and c) the number of nanoseconds since the start of the second. The counts of the days, the seconds and the nanoseconds since the epoch are all relative to Universal Time. The year/day-of-year designation is relative to the local time of the Timepoint instance. This internal representation scheme is one reason why Chronos is so performant relative to its competition.

So, given Timepoint's internal representation, leap seconds would only be relevant to the semantics of the internal representation of a Timepoint when it designates a point-in-time that corresponds to the occurrence of a leap second, and not otherwise. Leap seconds also would matter whenever one converts a Timepoint into a count of seconds since an epoch, or converts a count of seconds since an epoch into a Timepoint--but even then, the provider or consumer of the seconds-since-the-epoch count would have to be leap-second aware, which is not usually the case.


New Chronos Version Published (B1.001/2005-12-30T07:41:19+0000)

Version B1.001 of Chronos was published Fri, 30 Dec 2005 07:41:19 +0000 (UT: Universal Time). This version contains some performance enhancements, and some methods have been recoded for greater elegance.

Also, the following methods have been introduced:


As a result, Timepoint>>setTimeZone: now has semantics that are completely analogous to those of CalendricalCoordinate>>setCalendar:. Both methods now do nothing more than

a) resolve the argument into an instance either of ChronosTimezone or of Calendar (respectively,)
b) raise an Exception if the receiver isn't mutable, and
c) set the appropriate instance variable to the value represented by the method argument.

Previously, Timepoint>>setTimeZone: would convert the receiver from one time zone to another, if the receiver's time zone was not nil (behavior which was not analagous to that of CalendricalCoordinate>>setCalendar:.) Consequently, Timepoint>>setTimeZone: can no longer be used to rebind a (mutable) Timepoint to a different local time, while preserving the designated moment in Universal Time. Instead, Timepoint>>convertToTimeZone: must be used for that purpose.


Why Chronos?

I thought it would be appropriate to start my Chronos blog by explaining my motivations for creating and publishing the Chronos Date/Time Library.

It all started back in 1984, when my friend Kenton Hoover encouraged me to purchase a book named Smalltalk: The Language And Its Implementation (affectionately now known as the "Blue Book.") When I first read it, I did not have access to an actual Smalltalk implementation, and so failed to get the complete experience and complete understanding. Nevertheless, the book had a profound impact on my computer programming and computer science world view.

About a year later, a technical support person wheeled a Tektronix 4404 Smalltalk workstation into my cubicle at Bank America (in an office building on Spear Street in San Francisco.) Over the next few months, I came to fully understand the terms 'class,' 'object,' 'instance,' 'message,' 'method,' 'metaclass' and 'block,' in a way that transcended the level of understanding I had achieved from just reading the Blue Book. The mental transformation involved is not unlike the one that must happen in order for someone with an Aristotelian weltanschauung to grok Newton. [Most programmers have yet to benefit from an equivalent enlightenment, including many who think they already have. But more on that at some other time.]

Smalltalk was so far ahead of anything else available at the time, that fully experiencing and grokking it during the mid 1980's can best be compared to taking a ride in a time machine to a world decades in the future. But instead of enumerating all the advantages of Smalltalk compared to its mid-1980's competition, let me focus on just one small facet of the overall picture: Dates and Times (which are, after all, the subject of both this post and this blog.)

For most programming languages in 1985, the handling of dates and times was left to application coders to deal with as best they were able (ahem.) Which is not to say that there weren't reusable date/time libraries available for some of the major languages. For example, the <time.h> module of what is now the ANSI Standard C library came from code donated to 4.3BSD Unix by Arthur David Olson in 1986. The <time.h> module was incorporated into ANSI C in 1989.

By the standards of the day, <time.h> was in many ways rather superior to anything else that was commonly available. For one thing, it actually dealt with time zones in a reasonable way. For another, its internal representation of time was a count of seconds since an epoch, specified in Universal Time (which is often incorrectly referred to as either GMT or UTC—but more about that at some other time.) In this, C's <time.h> module was superior to Smalltalk's Date and Time classes. But in 1985 and early 1986, I didn't know any of that. In fact, I didn't even learn C until 1988, and didn't pay much attention to <time.h> until much later.

Unlike any other language with which I was familiar at the time, Smalltalk actually had dates and times as coherent, first-class values. You could assign them to variables, pass them as arguments, and return them as the result of a message send. You didn't need to know or care anything about the internal representation of a Date or Time object. Because of the way Smalltalk works, and because the Date and Time classes were included as part of the "standard class library," it was the equivalent of having Date and Time as "built in" data types in Pascal, Modula-2 or Ada.

The fact that "types" (classes) implemented by the programmer can have the same "look and feel" as "built-in" types is of course one of the major benefits of Smalltalk compared to most of its competition. Dates and Times are one of the more compelling concrete, non-theoretical examples of why that matters. In 1985, the idea of having a Date type and a Time type was a revolutionary advance.

From my 1985 perspective, Smalltalk started out in a situation where its support of Dates and Times was second to none. In 2004, when I started work on what is now the Chronos Date/Time Library, that was no longer the case. Chronos is my attempt to restore Smalltalk to the same position with respect to date/time handling that it enjoyed back in 1985 (as I saw it then.) I want the programmers of today to experience the same feeling of delight about Smalltalk's date/time capabibilities that I felt back in 1985. And I also hope to inspire others to make similar contributions to Smalltalk (and/or its deserving successors) in other domains.

Additionally, I want to encourage the various Smalltalk implementations to grow together, and not apart. Smalltalk needs a much wider and deeper "standard library" if it is going to survive. I hope that Chronos will be a significant contribution towards that goal.