Back in 2007 I wrote about some code I wrote in 2003. No idea if it'd be useful.
http://grokbase.com/t/perl/datetime/073612z62x/event-dst-pulling-dst-changes-from-datetime Cheers! Rick Measham 📱 On 23/05/2012, at 6:59, Anthony Ball <[email protected]> wrote: > I never had any luck finding anything to give me the future DST changes for > a timezone so I worked out how to get it on my own, but recently I upgraded > from something like DateTime 0.36 to 0.74 and something really strange is > happening. > > In my code I set the date to the start of the year and then use an > undocumented internal timezone call _span_for_datetime to get the next > change, then I pull utc_rd_as_seconds one subtracted from the other allows > me to add the proper seconds to move forward to the next change, store it, > then roll and repeat until I have what I want. Now however the second > change in 2012 is coming up one second short, even though the offsets are > the same, and it seems to be other timezones as well, not just New York. > Asia/Gaza for instance. > > Using the old code I get "2012-03-11T03:00:00 2012-11-04T01:00:00" for New > York, > but the new DateTime gives me "2012-03-11T03:00:00 2012-11-04T01:59:59", > one second before the actual change. > > Is this a bug in my code or something weird in DT. Of course I'm using > various calls that are unsupported externally so I shouldn't be surprised > when things go south, but the numbers are the same between one and the > other so maybe I'm doing something wrong, wouldn't surprise me. I even > tried converting to utc before doing my math and then back as the perldoc > suggests with no joy. > > A slightly simplified version of my code follows... I've found a workaround > but would like to understand the problem. > > use DateTime; > # pass year timezone > print "@{get_dst_changes($ARGV[0],$ARGV[1])}\n"; > > sub get_dst_changes { > my $year = shift; > my $tz = shift; > my ( $DT, $DT_end ); > > eval { $DT = DateTime->new( year => $year, time_zone => $tz ); }; > return if $@; > $DT_end = $DT->clone(); > $DT_end->add( years => 1 ); > > my $i = 0; > my @out; > my $DT2; > while ( $i++ < 100 ) { #in case we start looping for some reason > my $span = $DT->{tz}->_span_for_datetime( 'utc', $DT ); > my $seconds = $DT->utc_rd_as_seconds(); > > if ( $span->[UTC_END] =~ /\+/ ) { > last; > } > my $change = $span->[UTC_END] - $seconds; > > # Find the offset and add it. Now we have a DateTime object AT DST > change > $DT->add( seconds => $change ); > > $DT2 = $DT->clone(); > $DT->add( seconds => 1 ); # One second past allows us to search for > the next DST change > last unless $DT < $DT_end; > > push @out, $DT2; > } > \@out; > } > -- > Message protected for iSite by MailGuard: e-mail anti-virus, anti-spam and > content filtering.http://www.mailguard.com.au > Click here to report this message as spam: > https://login.mailguard.com.au/report/1EO02gepzC/1mXz3HoAzKmVJJ1MNVgifT/0.2 > -- Message protected for iSite by MailGuard: e-mail anti-virus, anti-spam and content filtering.http://www.mailguard.com.au
