|
|
ru.perl- RU.PERL ---------------------------------------------------------------------- From : yurik shestakov 2:5020/400 26 Jul 2004 22:12:33 To : …ўЈҐЁ© Љ®ў «м Subject : Re: разбор временного сеанса -------------------------------------------------------------------------------- On Mon, Jul 26, 2004 at 03:52:33PM +0000, Евгений Коваль wrote: ЕК> Hужно для обсчета диалапных сеансов по дневному/ночному/праздничному ЕК> тарифам. Вот такой у меня кусок остался из dialup-ного биллинга (сейчас сессии из tacacs-а обрабатываются программой на C). Использование было следующее: # объект TimeOverlap для пред. периода my $pp_obj = new TimeOverlap (ParseTools::dec_period($period), 2, 8); # объект TimeOverlap для тек. периода my $p_obj = new TimeOverlap ($period, 2, 8); # с 2 до 8 ночи -- бесплатно # stop_time -- время окончания сессии (в секундах с 1.1.1970) # elapsed_time -- продолжительность сессии в секундах #-- проверяем предыдущий период $night_t += $pp_obj->overlap2($stop_time-$elapsed_time, $stop_time); #-- проверяем текущий период $night_t += $p_obj->overlap2($stop_time-$elapsed_time, $stop_time); $elapsed_time -= $night_t; # по итогу: $elapsed_time -- тарифицируемое время (то, к-е оплачивается) ======================================================================== package TimeOverlap; # $Id: TimeOverlap.pm,v 1.2 2000/04/01 17:57:34 yu Exp $ #------------------------------------------------------------------------ require Exporter; require POSIX; use Carp; @TimeOverlap::EXPORT_OK = qw(new); @TimeOverlap::ISA = 'Exporter'; @TimeOverlap::nday = (31,29,31, 30,31,30, 31,31,30, 31,30,31); #=================================================================== sub _mktime { my @a = @_; my $t = POSIX::mktime(@a[0,1,2,3,4,5],0,0,0); my @lt = localtime($t); if ($lt[8]) { # is_dst == 1 ? $t = POSIX::mktime(@a[0,1,2,3,4,5],0,0,1); } return $t; } sub new { my ($class, $period, $start_hour, $stop_hour) = @_; my $start_t = $start_hour * 3600; my $stop_t = $stop_hour * 3600; croak "Stop_time is not great then start_time" unless $stop_t > $start_t; my ($mm,$yy) = ($period % 100, int($period/100)); croak "Invalid period: $period" unless $mm > 0 && $mm < 13 && $yy > 1990; my $self = bless { 'period' => $period, 'start' => $start_t, 'stop' => $stop_t, }; my $lastday = last_day($period); $self->{'last_day'} = $lastday; my $n; my @start_a; my @stop_a; $self->{start_aref} = \@start_a; $self->{stop_aref} = \@stop_a; $self->{period_start} = _mktime(0,0,0,1,$mm-1,$yy-1900); for ($n = 1; $n <= $lastday; $n++) { my $start_t = _mktime(0,0,$start_hour,$n,$mm-1,$yy-1900); my $stop_t = _mktime(0,0,$stop_hour,$n,$mm-1,$yy-1900); $start_a[ $n -1 ] = $start_t; $stop_a[ $n -1 ] = $stop_t; } return $self; } # ================================================================= sub last_day { my $period = shift; croak "last_day(): period is not defined" unless defined($period); my ($yy,$mm) = (int($period/100), $period % 100); croak "last_day(): invalid month: $mm" unless ($mm > 0 && $mm < 13); if ($mm == 2) { # Feb ? if ( (($yy % 4) == 0 && ($yy % 100) != 0) || ($yy % 1000) == 0) { return 29; } else { return 28; } } else { return $nday[$mm-1]; } } # ================================================================= sub overlap { my ($self,$start_t, $stop_t) = @_; #-- my ($X,$Y) = ($start_t, $stop_t); my ($summ,$n) = (0,0); my ($start_aref, $stop_aref) = map { $self->{$_} } qw(start_aref stop_aref); for (; $n < $self->{'last_day'} ; $n++ ) { my ($A, $B) = ($start_aref->[$n], $stop_aref->[$n]); next if $A > $Y || $B <= $X; my @ary = sort { $a <=> $b } ( $B-$A, $Y-$A, $B-$X, $Y-$X ); $summ += shift @ary; } return $summ; } # ================================================================= sub overlap2 { my ($self,$start_t, $stop_t) = @_; #-- my ($X,$Y) = ($start_t, $stop_t); my ($summ,$n) = (0,0); my ($start_aref, $stop_aref) = map { $self->{$_} } qw(start_aref stop_aref); my $d_start = int ( ($start_t - $self->{period_start}) / 86400 ); my $d_stop = int ( ($stop_t - $self->{period_start}) / 86400 ); # номер дня от начала месяца (дробный) $d_start = 0 if ($d_stop < 0); $d_stop = $self->{'last_day'}-1 if $d_stop > $self->{'last_day'} -1; for ($n = $d_start; $n <= $d_stop ; $n++ ) { my ($A, $B) = ($start_aref->[$n], $stop_aref->[$n]); next if $A > $Y || $B <= $X; my @ary = sort { $a <=> $b } ( $B-$A, $Y-$A, $B-$X, $Y-$X ); $summ += shift @ary; } return $summ; } 1; ======================================================================== -- // yurik shestakov --- ifmail v.2.15dev5.3 * Origin: Unknown (2:5020/400) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.perl/10069376cb231.html, оценка из 5, голосов 10
|