- I had a starting date in october and I wanted to know the end date after N spring-neap cycles (in my approximation: 15 days and 6 hours).
- I used the clock command to do the computation and got some date in january, 7 o'clock as the stop date/time.
# Daylight saving problems # # No care for daylight saving time corrections ... # set day1 [clock scan "2005-10-01"] set day2 [clock scan "2005-11-01"] set number_days [expr {($day2-$day1)/86400.0}] puts "Number of days: $number_days" # Option: -gmt 1 # set day1 [clock scan "2005-10-01" -gmt 1] set day2 [clock scan "2005-11-01" -gmt 1] set number_days [expr {($day2-$day1)/86400.0}] puts "Number of days: $number_days"The result (Tcl 8.4):
Number of days: 31.0416666667 Number of days: 31.0Of course, it depends on what you want to achieve, if you need this option or not. Date/time computations are simply very complicated.
LV A friend sent me this pointer [1] which discusses the fact that a number of countries have been, and continue to, make changes in the way DST is calculated. Does anyone know whether Tcl is tracking these kinds of adjustments?MG As far as I know, all Tcl's time functions are platform-dependent, so as long as the underlying OS knows about them, Tcl will too.LV Certainly in Tcl 8.5, there is now a large amount of timezone information. I just don't know enough about those files to know whether Tcl software has to change, given that there seems to be discussion of things like java changes. Just was curious.MG tends to forget 8.5 - my comments were aimed more at 8.4. I'm not sure how the additional things in 8.5 work.KBK answers LV's question with 'Yes.' Tcl is indeed tracking time zone changes, and you can expect that it will continue to do so. Unlike Windows, it also returns correct historical time information, at least back to 1970 or so. That said, on most Unix systems you will also need to keep 'zoneinfo' up to date; it's common to omit Tcl's tzdata from an installation if the local machine has the equivalent in 'zoneinfo'. Also, the ':localtime' time zone does whatever the underlying OS and C library do.Knowing what part of the world Larry comes from, I must caution that it does not have correct information for certain West Virginia counties from the 1960's - the rules for Daylight Saving Time there were both controversial and contradictory. I doubt that very many people there actually knew what time it was in the next town over. I certainly doubt that they changed their watches half-a-dozen times in an hour-long bus ride simply because the different towns had different rules. (If memory serves, some had yet to adopt Standard Time and set the courthouse clock to local mean solar time!)LV Amusingly enough, I lived in WV during that time period, and know EXACTLY the situation to which Kevin refers.The article at [2] includes a section titled Inconsistent use in the U.S. which makes reference to the situation - note that I lived about 5 seconds off Route 2, about 15-20 minutes south of the bus route mentioned...
LV If the date occurs before "1970 or so" , does Tcl default back to the OS's zoneinfo or whatever? Or does it just not try?I understand that the timezone info isn't granular enough to handle the special cases of a particular county or town which decides not to observe DST.KBK Your understanding is incomplete. Arthur Olson, from whom I get the data, makes an effort to keep the timezone info granular enough. Indiana, for instance, is divided into locales,
- 'America/Indiana/Indianapolis',
- 'America/Chicago' (these two cover most of the cases),
- 'America/New_York' (Dearborn and Ohio Counties),
- 'America/Kentucky/Louisville' (Clark, Floyd and Harrison Counties),
- 'America/Indiana/Vincennes' (Daviess, Dubois, Knox, Martin, and Perry Counties),
- 'America/Indiana/Marengo' (a township in Crawford County),
- 'America/Indiana/Petersburg' (Pike County),
- 'Anerica/Indiana/Winamac' (Pulaski County),
- 'America/Indiana/Knox' (Starke County), and
- 'America/Indiana/Vevay' (Switzerland County).
LV Is there a way to write Tcl code that could be used to answer the question "for timezone ABC, on a particular date and time, was daylight savings time in effect"?LV Later... I thought about using
clock format now -format {Z} -timezone $whateverand comparing the timezone against a known value. Alas, that fails, for example, in Melbourne Austraila, where the 3 letter abbreviation for non-daylight is EST - Eastern Standard Time and for daylight savings is EST - Eastern Summer (Daylight) Time.Yuck.LV Even later - I tried to poke inside Tcl 8.5's clock.tcl , to invoke the internal pieces of clock to get at the date and time parsing code, but so far, I've not success getting the right pieces to play nicely with one another.KBK For some locales and times, the question isn't even meaningful. What do you want it to return for a locale that has advanced its clock two hours (e.g. Israel right after independence, or Newfoundland in 1988)? For a locale that temporarily reverts to solar time from Standard Time (Detroit in 1902)? For things like 'Eastern War Time'? You can use the %z format group to get the time zone's offset from Greenwich, and compare that against a known value, I suppose. If the intent of your question was to determine, "what is the offset from Greenwich in a particular locale on a particular date and time?" then %z is surely the answer. (Caveat: 8.5 only!)LV My intent is to display an indicator if the time being displayed is considered daylight savings time. The other special times is not relevant in my particular situation. I have no idea why the original specifications cared about DST. But it did, and now I am trying to rewrite code in C, providing identical output, but with the better stability and more intelligent behavior of Tcl 8.5. At this point in time, I can't, because of the lack of a dst indicator.Alastair Davies wonders about this:
proc is_dst {time tz} { set year [clock format $time -format %Y -timezone $tz] set midsummer [clock scan "21 06 $year" -format "%d %m %Y" -timezone $tz] set midwinter [clock scan "21 12 $year" -format "%d %m %Y" -timezone $tz] set midsummer_offset [scan [clock format $midsummer -format %z -timezone $tz] %d] set midwinter_offset [scan [clock format $midwinter -format %z -timezone $tz] %d] if {$midsummer_offset == $midwinter_offset} { return -code error "DST not in use in locale $tz" } if {$midsummer_offset < $midwinter_offset} { #-- In southern hemisphere set temp $midwinter_offset set midwinter_offset $midsummer_offset set midsummer_offset $temp } set offset [scan [clock format $time -format %z -timezone $tz] %d] if {$offset == $midsummer_offset} { return true } elseif {$offset == $midwinter_offset} { return false } else { return -code error "Something crazy happened" } }For example,
is_dst [clock scan now] :Europe/London is_dst [clock scan now] :Australia/Sydney is_dst [clock scan now] :Australia/Perth set tz ":Israel" set time [clock scan "20 08 1948" -format "%d %m %Y" -timezone $tz] is_dst $time $tzLV Wow - thanks!Hey, can you check
is_dst [clock scan now] :US/PacificFor some reason, on my tcl 8.5 system, that seems to come up saying today is daylight savings time...Alastair Davies Sorry. I've just added a sprinkling of scan offset %d to convert the reported offsets (in the form -0700 or +0100) to decimal numbers. These seem to compare more reliably.
% set tz ":US/Pacific" :US/Pacific % is_dst [clock scan "11 4 2007" -format "%m %d %Y" -timezone $tz] $tz true % is_dst [clock scan "11 5 2007" -format "%m %d %Y" -timezone $tz] $tz falseIs this the right date for the change?LV The examples you provide here appears to be right. Does this example look peculiar to you?
puts "LA DST Apr 2, 2006? [is_dst [clock scan "April 01, 2006 03:00 AM"] :US/Pacific]" puts "LA DST Apr 1, 2006? [is_dst [clock scan "April 01, 2006 03:00 AM"] :US/Pacific]" puts "LA DST Mar 31, 2006? [is_dst [clock scan "March 31, 2006 03:00 AM"] :US/Pacific]" LA DST Apr 2, 2006? false LA DST Apr 1, 2006? false LA DST Mar 31, 2006? falseI would have thought that the Apr 1 and 2 examples would be true...Alastair Davies A few points, in no particular order, and with absolutely no authority:
- If the time change is made in the same way as in Europe, I would expect it to be at 2am on Sunday morning, i.e. 2 April 2006 (though the actual date is different from when Europe changes).
- I understand the clock scan command in 8.5 should usually be used with a format specifier, to invoke the new parser. (Without a format specifier I believe the old ambiguities of the 8.4 parser can cause problems.) The clock scan command can also be used with a timezone specifier, to determine to what time zone the given string is referring. If your computer is not in the :US/Pacific time zone, the result will represent the time in your own time zone, not Los Angeles.
- Bearing both these in mind, I am encouraged by these two results. (They could be wrong, but they are at least plausible.)
% is_dst [clock scan "04/02/2006 01:00" -format "%m/%d/%Y %H:%M" -timezone :US/Pacific] :US/Pacific false % is_dst [clock scan "04/02/2006 03:00" -format "%m/%d/%Y %H:%M" -timezone :US/Pacific] :US/Pacific true
- I think there is also a typo in your entry above, which may have been all that was puzzling you. (The first two commands both refer to April 01.)
LV Different tangent - who actually creates the names for the timezones, anyways? I mean, the longer, supposedly preferred, names are all over the map, so to speak. For instance, I see:
- :US/Eastern
- :Europe/Paris
- :Portugal
- :US/Eastern - A 'legacy' synonym for :America/New_York
- :Europe/Paris - A name that fits the system.
- :Portugal - A 'legacy' synonym for :Europe/Lisbon