Re: Issue with finding next DST change, date math error?

[email protected] (Rick Measham)
Newsgroups perl.datetime
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.