'''Purpose: ''' [Kevin Kenny] is comtemplating starting a project to rework the [clock] command. The purpose of this page is to present some of the issues with the current clock command, and collect feedback about how best to fix it. I wish I had time to more than merely applaud Kevin's work. This is long overdue! -- [CLN] ---- The current (Tcl 8.4a3) clock command has served us well since Tcl 7.5, but it's starting to show cracks at all levels. It appears that nothing less than a complete rework may suffice to fix all the issues. (In that case, the existing [[clock]] command will be preserved, but deprecated.) '''1. The measurement of time.''' ''Mickey's little hand is on the six, and his big hand is on the nine.'' At present, Tcl's concept of absolute time is the count of seconds from a fixed ''epoch'' or zero point. The count is expressed as a signed 32-bit integer. This representation has a number of drawbacks. * ''Range.'' The representation of time cannot represent dates before 1902 nor after 2038. It is only a few years before banking applications, for instance, which deal with 30-year loans will run into the end of the permissible range. * ''Precision.'' The granularity of a second is not adequate for disambiguating timestamps in a number of applications. Now that NTP is a near-universal part of the networking infrastructure, it is routine to keep different systems' clocks synchronized to within a few milliseconds to tens of milliseconds, and one would want to time-stamp actions * ''Epoch differences.'' The time returned by [[clock seconds]] is relative to the time epoch of the underlying operating system, and the choice of epoch varies. This should be hidden from the user. * ''Non-uniform representation of time intervals.'' Most systems return absolute time as a count of nominal seconds of UTC from some epoch, ignoring leap seconds; two times that are a day apart will show precisely 86400 seconds (never 86399 nor 86401) between them, even if a leap second has occurred in between. A few systems (at least certain configurations of FreeBSD) return, instead, a count of seconds of TAI, and on these systems a day will be a second long or short if a leap second occurs. ''Proposal:'' Add to [[clock]] a [[clock milliseconds]] command that returns the nominal time from the Julian epoch expressed in milliseconds as a double-precision floating-point number. Double-precision floating point is chosen as a representation because it is available on all the platforms, unlike 64-bit integers, which are the most obvious alternative. The granularity of milliseconds, rather than seconds or days, ensures that any integer number of milliseconds will be represented exactly. The Julian epoch is chosen because many existing calendar algorithms, such as those published in the second edition of Reingold [http://emr.cs.uiuc.edu/~reingold/calendars.shtml], use Julian day number as their internal representation. The Julian day can be obtained from the millisecond count simply by dividing by 86400000 and casting to an integer. Since leap seconds cannot be predicted in advance, it is useful to assume that the day has a fixed length of 86400 seconds. For this reason, I propose that the Tcl clock be Smoothed Universal Time (UTS) [http://www.cl.cam.ac.uk/~mgk25/uts.txt]. The code in ''TclpGetTime'' on the Unix platform (where the kernel clock is corrected with ''adjtime'') and on the Windows platform (where the Tcl clock is derived from a separate 'performance counter' that is disciplined with a phase-locked loop to the system clock) already comes close to the desired behavior. ---- '''2. Calendar''' ''I've been on a calendar, but never on time.'' - Marilyn Monroe The handling of the calendar is lacking some points that various users have requested. * There is no input of dates in the ISO calendar, e.g., 2001-W45-3 for "the third day of fiscal week 45 in 2001." Even the output of ISO dates has errors, since the calendar year and the fiscal year usually differ in either the first week of January or the last week of December. * There is no handling of "week of month" ("the fourth week of November"), needed for handling of certain daylight saving time locales. * There is no provision whereby the output could be localized to a non-Gregorian calendar. (Several locales still use traditional Hebraic or Islamic calendars as the civil calendar!) * There is no representation for multiple eras (BC/AD; the Japanese "Year of the Emperor"; the Islamic "anno Hegirae"; the Hebraic "anno mundi"; etc.) For what it's worth, there's information on various calendars at http://www.copi.org/craig/events/calendar.html. -- [CLN] ---- '''3. Time zone''' ''At the back of the Daylight Saving scheme I detect the bony, blue-fingered hand of Puritanism, eager to push people into bed earlier, and get them up earlier, to make them healthy, wealthy and wise in spite of themselves.'' - Robertson Davies Conversion of times between local and UTC (mislabelled, 'GMT,' in the Tcl documentation) depends on the calculations of the underlying system. * These calculations are often of poor quality (witness the famous 'April Fool' bug in Windows [http://msdn.microsoft.com/visualc/headlines/2001.asp], which is known to have caused a costly failure of at least one Tcl application). * Many of the underlying systems are capable of handling only a single rule for daylight saving time conversion. If the rules change, they fail to work. (In the pre-Tcl days, a number of applications failed in 1987 when the US Congress changed the dates on which daylight saving time began and ended.) * The time zone calculations cannot be localized for locales with unequal hours (several locales, particularly in Arab countries, still maintain solar hours as the civil time). * The system allows for only two time zones in an application, local time and UTC. Consider the case of a television station application wishing to report three times, local, UTC, and time at network headquarters in New York. -- particularly if the station's locale observes different daylight saving time rules than New York. (Or consider time clocks on Hoover Dam: one end of the dam is in Arizona which never observes DST, the other is in Nevada which '''does''' observe DST! -- [CLN]) * Choosing a time zone other than that of the local system is perilous; the handling of the TZ environment variable is capricious. * Input and output of time zones is by time zone name, which differs not only among languages and locales but also between operating environments. (I've seen my local time zone reported as EST, EST5EDT, -05, -0500, R, Eastern Standard Time, and America/New_York, among others.) This inconsistency causes severe difficulty attempting to parse the time zone on the way back into Tcl. There is no provision for output of the time zone in numeric form; [[clock format]] cannot produce, for instance, a date in RFC2822 form. ---- '''4. Localization and input/output issues''' ''...ad calendas gr�cas reponere.'' Tcl's handling of time ignores the locale. In many cases, it simply cannot be localized easily. Moreover, Tcl's input conversion for times suffers from an attempt to be excessively general; it succeds only in having peculiar bugs. * [[clock scan]] and [[clock format]] are not localized; they always use the defaults for the 'C' locale. They need to specify at least the standard language_country_variant locales, plus two more: ''system'' for the system's default locale, and ''user'' for the user's default. * [[clock scan]] also cannot be localized to specify, for instance, whether a given locale expresses dates as mm-dd or dd-mm. * The implementation of [[clock scan]] as a YACC parser without any indication on the command line of the expected format is dreadful. Attempting to deduce from context whether '2000' represents a year, eight o'clock in the evening, a hypothetical time zone (there is no time zone twenty hours east of Greenwich, but the syntax allows for it), or a numeric quantity (2000 seconds, for instance) results in a parser that satisfies nobody. * Use of [[clock scan]] for date and time arithmetic is one reason that it attempts to be a universal tool. It would be nice to have date arithmetic analogous to the ''Calendar'' classes in Java [http://java.sun.com/j2se/1.4/docs/api/java/util/Calendar.html] or ICU [http://oss.software.ibm.com/icu/userguide/dateCalendar.html]. There is no clear alternative to code that does things like set nextMonth [clock scan {+1 month} -base $today] [AK]: See http://www.purl.org/net/akupries/soft/pool/f_base_date.tcl.html ---- '''5. Some contemplations''' ''Tempora mutantur et nos in illis'' [Arjen Markus] I have a number of remarks about the previous sections: * Why not introduce an option -milliseconds to the [clock seconds] command? Have it return the number of seconds as an integer number if this option is not present and otherwise as a double value. * Even more adventurous: if we let [clock seconds] always return a double value, would that break any existing scripts? Only those that somehow explicitly assume the time to be an integer number? * If we leave the [clock seconds] as it is and introduce a new command [clock milliseconds] that uses Julian epoch, how do we know the relationship between the two? That suggests the base for [clock] to be Julian in all cases. * If we change the base for the [clock] command, then what other commands need reworking? Surely [file stat] is one: we want any date/time as represented by a single number to be comparable, in my opinion. * How does the conversion from actual time to integer seconds work? Is that a rounding-off or a truncation? Probably the underlying system is responsible. * If we have [clock seconds] return a double value, then [clock format] and [clock scan] need revision as well. There is a clear advantage over the introduction of a separate Julian date and time: the result of any [clock] command would be compatible with any other time. * One limitation of the current [clock scan] command is that to parse non-English names of the months you have to build your own scanner. Though English is ubiquitous, it is not the only language found on computers. * Another one is the order in which months, days and years are presented and the separating characters. I am well aware of the fact that this leads to considerable ambiguities, but, well, these may be solved conveniently with a Java-like Calendar package. For instance, a date like 2001/05/01 would be written as "1 mei 2001" in Dutch and "1. Mai 2001" in German, or, numerically, "1/5/2001", respectively, "1.5.2001" * Fairly arbitrary arithmetic is possible via Julian date/time: Mike Hall has a nice beginning of such a package at . What is lacking there is the manipulation via explicit procedures of hours, minutes and seconds. ----