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

Reply via email to