⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timezone.pm

📁 1. 记录每个帖子的访问人情况
💻 PM
📖 第 1 页 / 共 2 页
字号:
package DateTime::TimeZone;use strict;use vars qw( $VERSION );$VERSION = '0.2601';use DateTime::TimeZoneCatalog;use DateTime::TimeZone::Floating;use DateTime::TimeZone::Local;use DateTime::TimeZone::OffsetOnly;use DateTime::TimeZone::UTC;use Params::Validate qw( validate validate_pos SCALAR ARRAYREF BOOLEAN );use constant INFINITY     =>       100 ** 100 ** 100 ;use constant NEG_INFINITY => -1 * (100 ** 100 ** 100);# the offsets for each span elementuse 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 new{    my $class = shift;    my %p = validate( @_,                      { name => { type => SCALAR } },                    );    if ( exists $DateTime::TimeZone::LINKS{ $p{name} } )    {        $p{name} = $DateTime::TimeZone::LINKS{ $p{name} };    }    elsif ( exists $DateTime::TimeZone::LINKS{ uc $p{name} } )    {        $p{name} = $DateTime::TimeZone::LINKS{ uc $p{name} };    }    unless ( $p{name} =~ m,/, )    {        if ( $p{name} eq 'floating' )        {            return DateTime::TimeZone::Floating->new;        }        if ( $p{name} eq 'local' )        {            return DateTime::TimeZone::Local::local_time_zone();        }        if ( $p{name} eq 'UTC' || $p{name} eq 'Z' )        {            return DateTime::TimeZone::UTC->new;        }        return DateTime::TimeZone::OffsetOnly->new( offset => $p{name} );    }    my $subclass = $p{name};    $subclass =~ s/-/_/g;    $subclass =~ s{/}{::}g;    my $real_class = "DateTime::TimeZone::$subclass";    unless ( $real_class->can('instance') )    {        eval "require $real_class";        if ($@)        {            my $regex = join '.', split /::/, $real_class;            $regex .= '\\.pm';            if ( $@ =~ /^Can't locate $regex/i )            {                die "The timezone '$p{name}' could not be loaded, or is an invalid name.\n";            }            else            {                die $@;            }        }    }    return $real_class->instance( name => $p{name}, is_olson => 1 );}sub _init{    my $class = shift;    my %p = validate( @_,                      { name     => { type => SCALAR },                        spans    => { type => ARRAYREF },                        is_olson => { type => BOOLEAN, default => 0 },                      },                    );    my $self = bless { name     => $p{name},                       spans    => $p{spans},                       is_olson => $p{is_olson},                     }, $class;    foreach my $k ( qw( last_offset last_observance rules max_year ) )    {        my $m = "_$k";        $self->{$k} = $self->$m() if $self->can($m);    }    return $self;}sub is_olson { $_[0]->{is_olson} }sub is_dst_for_datetime{    my $self = shift;    my $span = $self->_span_for_datetime( 'utc', $_[0] );    return $span->[IS_DST];}sub offset_for_datetime{    my $self = shift;    my $span = $self->_span_for_datetime( 'utc', $_[0] );    return $span->[OFFSET];}sub offset_for_local_datetime{    my $self = shift;    my $span = $self->_span_for_datetime( 'local', $_[0] );    return $span->[OFFSET];}sub short_name_for_datetime{    my $self = shift;    my $span = $self->_span_for_datetime( 'utc', $_[0] );    return $span->[SHORT_NAME];}sub _span_for_datetime{    my $self = shift;    my $type = shift;    my $dt   = shift;    my $method = $type . '_rd_as_seconds';    my $end = $type eq 'utc' ? UTC_END : LOCAL_END;    my $span;    my $seconds = $dt->$method();    if ( $seconds < $self->max_span->[$end] )    {        $span = $self->_spans_binary_search( $type, $seconds );    }    else    {        my $until_year = $dt->utc_year + 1;        $span = $self->_generate_spans_until_match( $until_year, $seconds, $type );    }    # This means someone gave a local time that doesn't exist    # (like during a transition into savings time)    unless ( defined $span )    {        my $err = 'Invalid local time for date';        $err .= ' ' . $dt->iso8601 if $type eq 'utc';        $err .= " in time zone: " . $self->name;        $err .= "\n";        die $err;    }    return $span;}sub _spans_binary_search{    my $self = shift;    my ( $type, $seconds ) = @_;    my ( $start, $end ) = _keys_for_type($type);    my $min = 0;    my $max = scalar @{ $self->{spans} } + 1;    my $i = int( $max / 2 );    # special case for when there are only 2 spans    $i++ if $max % 2 && $max != 3;    $i = 0 if @{ $self->{spans} } == 1;    while (1)    {        my $current = $self->{spans}[$i];        if ( $seconds < $current->[$start] )        {            $max = $i;            my $c = int( ( $i - $min ) / 2 );            $c ||= 1;            $i -= $c;            return if $i < $min;        }        elsif ( $seconds >= $current->[$end] )        {            $min = $i;            my $c = int( ( $max - $i ) / 2 );            $c ||= 1;            $i += $c;            return if $i >= $max;        }        else        {            # Special case for overlapping ranges because of DST and            # other weirdness (like Alaska's change when bought from            # Russia by the US).  Always prefer latest span.            if ( $current->[IS_DST] && $type eq 'local' )            {                my $next = $self->{spans}[$i + 1];                if ( ( ! $next->[IS_DST] )                     && $next->[$start] <= $seconds                     && $seconds        <= $next->[$end]                   )                {                    return $next;                }            }            return $current;        }    }}sub _generate_spans_until_match{    my $self = shift;    my $generate_until_year = shift;    my $seconds = shift;    my $type = shift;    my @changes;    my @rules = @{ $self->_rules };    foreach my $year ( $self->{max_year} .. $generate_until_year )    {        for ( my $x = 0; $x < @rules; $x++ )        {            my $last_offset_from_std;            if ( @rules == 2 )            {                $last_offset_from_std =                    $x ? $rules[0]->offset_from_std : $rules[1]->offset_from_std;            }            elsif ( @rules == 1 )            {                $last_offset_from_std = $rules[0]->offset_from_std;            }            else            {                my $count = scalar @rules;                die "Cannot generate future changes for zone with $count infinite rules\n";            }            my $rule = $rules[$x];            my $next =                $rule->utc_start_datetime_for_year                    ( $year, $self->{last_offset}, $last_offset_from_std );            # don't bother with changes we've seen already            next if $next->utc_rd_as_seconds < $self->max_span->[UTC_END];            push @changes,                DateTime::TimeZone::OlsonDB::Change->new                    ( type => 'rule',                      utc_start_datetime   => $next,                      local_start_datetime =>                      $next +                      DateTime::Duration->new                          ( seconds => $self->{last_observance}->total_offset +                                       $rule->offset_from_std ),                      short_name =>                      sprintf( $self->{last_observance}->format, $rule->letter ),                      observance => $self->{last_observance},                      rule       => $rule,                    );        }    }    $self->{max_year} = $generate_until_year;    my @sorted = sort { $a->utc_start_datetime <=> $b->utc_start_datetime } @changes;    my ( $start, $end ) = _keys_for_type($type);    my $match;    for ( my $x = 1; $x < @sorted; $x++ )    {        my $last_total_offset =            $x == 1 ? $self->max_span->[OFFSET] : $sorted[ $x - 2 ]->total_offset;        my $span =            DateTime::TimeZone::OlsonDB::Change::two_changes_as_span                ( @sorted[ $x - 1, $x ], $last_total_offset );        $span = _span_as_array($span);        push @{ $self->{spans} }, $span;        $match = $span            if $seconds >= $span->[$start] && $seconds < $span->[$end];    }    return $match;}sub max_span { $_[0]->{spans}[-1] }sub _keys_for_type{    $_[0] eq 'utc' ? ( UTC_START, UTC_END ) : ( LOCAL_START, LOCAL_END );}sub _span_as_array{    [ @{ $_[0] }{ qw( utc_start utc_end local_start local_end offset is_dst short_name ) } ];}sub is_floating { 0 }sub is_utc { 0 }sub name      { $_[0]->{name} }sub category  { (split /\//, $_[0]->{name}, 2)[0] }sub is_valid_name{    my $tz = eval { $_[0]->new( name => $_[1] ) };    return $tz && UNIVERSAL::isa( $tz, 'DateTime::TimeZone') ? 1 : 0}sub STORABLE_freeze{    my $self = shift;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -