[EMAIL PROTECTED] wrote: > C:\>perl oddhours.pl 2007 > 2007-12-09 24.5 America/Caracas > 2007-03-11 22 America/Indiana/Winamac > 2007-03-25 24.5 Australia/Lord_Howe > 2007-10-28 23.5 Australia/Lord_Howe
Interesting, Australia/Lord_Howe does a half-hour DST shift every year. > 1961-01-01 23.7458333333333 Africa/Dar_es_Salaam That's the switch from an unaligned +02:44:45 to the regular +03:00. Curiously, it went to +02:44:45 *from* +03:00 earlier, in 1948, and before that (until 1931) it had used +02:37:08. Strong odour of politics. > C:\>perl oddhours.pl 1967 > Invalid local time for date in time zone: Africa/Casablanca Wow, someone *does* switch at noon. Or did, once. A quick look at the tzdata files shows a handful of other noon switches, all one-offs. I think you're going to have to give up the idea of using a fixed local time each day as your reference point. You need a function that finds the earliest point that lies within a given calendar date in local time, which will usually (but not always) be labelled 00:00. It's probably safer to work in UTC and convert to local, rather than work with local time-of-day directly, to avoid trouble with ambiguous times of day (there might be two instances of local 00:00 in one day). This is still assuming that the extent of each local calendar day is contiguous. If the clocks go back an hour at 00:30 local time, it would break your model. The Alaskan zones stretch the model to the limit, having in 1867 a jump back by 24 hours at 24:00 local time, yielding a 48-hour day. (Subjectively it was treated as two consecutive Fridays, which would have had the same calendar date were it not for the simultaneous switch from the Julian calendar to the Gregorian calendar.) There are also some Pacific islands that have jumped across the IDL in the other direction, skipping a calendar date altogether. Anyway, have a go with this function: sub day_start($$$$) { my($zone, $y, $m, $d) = @_; my $p = DateTime->new(time_zone=>"UTC", year=>$y, month=>$m, day=>$d, hour=>12); (my $rd) = $p->utc_rd_values; while(do { (my $l = $p->clone)->set_time_zone($zone); [$l->local_rd_values]->[0] } >= $rd) { $p->subtract(hours=>1); } while(do { (my $l = $p->clone)->set_time_zone($zone); [$l->local_rd_values]->[0] } < $rd) { $p->add(hours=>1); } my $q; while(1) { ($q = $p->clone)->subtract(minutes=>1); last if do { (my $l = $q->clone)->set_time_zone($zone); [$l->local_rd_values]->[0] } < $rd; $p = $q; } while(1) { ($q = $p->clone)->subtract(seconds=>1); last if do { (my $l = $q->clone)->set_time_zone($zone); [$l->local_rd_values]->[0] } < $rd; $p = $q; } return $p; } -zefram