Главная страница


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)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 разбор временного сеанса   …ўЈҐ­Ё© Љ®ў «м   26 Jul 2004 19:52:33 
 Re: разбор временного сеанса   yurik shestakov   26 Jul 2004 22:12:33 
Архивное /ru.perl/10069376cb231.html, оценка 1 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional