On Fri, Jul 23, 2010 at 04:39:58PM +0100, Elliot Merrony wrote:
> Hi all
> 
> I filed this bug last week and Dave Rolsky advised me to post here
> to explain what I was trying to do:

I created a simple lib to do this, though it really should be made available in 
the main libs. It takes a year or range of years and looks at the internals to 
find the DST transitions for the years in question.

Here it is. (tried to send when you first posted, but I'm having mail server 
issues)

#!perl
package TZInfo;
use strict;
use DateTime;
use POSIX;
use constant UTC_START   => 0;
use constant UTC_END     => 1;
use constant LOCAL_START => 2;
use constant LOCAL_END   => 3;
use constant OFFSET      => 4;
use constant IS_DST      => 5;
use constant SHORT_NAME  => 6;

sub get_dst_lib_info {
    {  version      => DateTime::TimeZone::Catalog::Olson   Version(),
       last_updated => ( stat( $INC{'DateTime/TimeZone/Catalog.pm'} ) )[9]
    };
}

# call with year or array ref of two years for range and timezone to check.
sub get_dst_changes {
    my $year = shift;
    my $tz   = shift;
    my ($DT,$DT_end);
    if(ref $year eq 'ARRAY') {
        eval { $DT = DateTime->new( %{$year->[0]}, time_zone => $tz ) };
        return if $@;
        eval { $DT_end = DateTime->new( %{$year->[1]}, time_zone => $tz ) };
        return if $@;
   } else {
        eval { $DT = DateTime->new( year => $year, time_zone => $tz ); };
        return if $@;
        $DT_end = $DT->clone();
        $DT_end->add( years => 1 );
    }
    my $i = 100;
    my @out;

    while ( $i-- ) {    #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->
        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 );             
        my $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;
}
1;

Reply via email to