?
Solved

Perl CGI time calculation

Posted on 2011-04-19
4
Medium Priority
?
419 Views
Last Modified: 2013-12-25
Any help would be appreciated.

I am displaying a summary of a user on the system using the 'last' command in the below format.
I am having difficulty with the 'Running Total' column where it keeps track of a running total
of the time logged in.


Login #            Date/Time                        Duration              Running Total
1         Mon Apr 11 18:24 - 18:27          00:03              Days, 0 hours, and 03 minutes
2         Sun Apr 10 18:42 - 21:31          02:49              Days, 2 hours, and 52 minutes
3         Sat Apr 9 14:19 - 14:33            00:13               Days, 3 hours, and  5 minutes
4         Wed Apr 6 21:58 - 22:26           00:28              Days, 3 hours, and 33 minutes
5          Wed Apr 6 20:18 - 21:56          01:38              Days, 4 hours, and 11 minutes
my @list = (`last | less`)

    Tr ( td({-style => 'width: 10%'},("Login #")), td({-style => 'width: 30%'},("Date/Time")),  td({-style => 'width: 10%'},("Duration")), td({-style => 'width: 50%'},("Running Total")) )
);

if ( my @input = grep /^\s*$user\b/, @list)
  {
       for ( my $i = 1; $i <= $#input; $i++ )
        {
 
   $input[$i] =~ /(\S+)\s+pts\/\S+\s+\S+\s+(\S+\s+\S+\s+\d+\s+\d+\:\d+\s+\S*\s+\S*\s*\w*)\(*(\d*)\:*(\d*)\)*/g;

print table
        (
                {-border=>0, width=>"55%"},
 Tr ( td({-style => 'width: 10%'},($i)), td({-style => 'width: 30%'},($2)),  td({-style => 'width: 10%'},($3.":".$4)) ,  td({-style => 'width: 50%'},( $0."Days, ".$0." hours, and ".0." minutes")))
        );
   }

Open in new window

0
Comment
Question by:fac66
  • 2
  • 2
4 Comments
 
LVL 27

Expert Comment

by:wilcoxon
ID: 35430097
Can you post the output of your 'last' command?  It does not appear to match what last outputs on my system (or else the "$input[$i] =~ /.../" has issues).
0
 

Author Comment

by:fac66
ID: 35431967
Running 'last|less' on my system:

nrisner  pts/0         81.213.156.102   Wed Apr 20 04:59 - 05:03  (00:04)
nrisner  pts/0         81.213.156.102   Wed Apr 20 04:44 - 04:49  (00:05)
bessler  pts/1        cm-204-193-202-2 Wed Apr 20 02:20 - 02:58  (00:37)
bessler  pts/1        cm-204-193-202-2 Wed Apr 20 01:29 - 01:59  (00:29)
kchin    pts/4          ip24-252-49-142. Wed Apr 20 00:36 - 00:39  (00:03)
kkrejci  pts/4           ip72-206-107-124 Wed Apr 20 00:25 - 00:30  (00:04)
nleonard pts/0        ip174-71-94-187. Tue Apr 19 23:59 - 02:37  (02:37)

I am back referencing for user ($1), date/time ($2), and broke up hour($3) & minute ($4)

 $input[$i] =~ /(\S+)\s+pts\/\S+\s+\S+\s+(\S+\s+\S+\s+\d+\s+\d+\:\d+\s+\S*\s+\S*\s*\w*)\(*(\d*)\:*(\d*)\)*/g;
0
 
LVL 27

Accepted Solution

by:
wilcoxon earned 2000 total points
ID: 35436877
I think this should work.  I also tweaked your regex slightly.
#!/usr/local/bin/perl

use strict;
use warnings;
use CGI qw(:standard);

my $user = 'somebody';

my @list = `last`;
#my @list = <DATA>;

print CGI->start_table({-border=>0, width=>'55%'}),
    Tr (td({-style => 'width: 10%'},"Login #"),
        td({-style => 'width: 30%'},"Date/Time"),
        td({-style => 'width: 10%'},"Duration"),
        td({-style => 'width: 50%'},"Running Total") ),
    "\n";

if ( my @input = grep /^\s*$user\b/, @list) {
    my @cum = (0, 0, 0);
    for (my $i = 0; $i < @input; $i++ ) {
 
        next unless ($input[$i] =~ /^\s*\S+\s+pts\/\S+\s+\S+\s+(\S+\s+\S+\s+\d+\s+\d+:\d+\s*\S*\s*\S*\s+)\(*(\d*)\:*(\d*)\)*/);

        my ($dt, $hr, $min) = ($1, $2, $3);
        add_dur(\@cum, $hr, $min);
        print 
            Tr (td({-style => 'width: 10%'}, $i),
                td({-style => 'width: 30%'}, $dt),
                td({-style => 'width: 10%'}, "$hr:$min"),
                td({-style => 'width: 50%'},
                    sprintf("%d days, %d hours, %d minutes", @cum) ) ),
            "\n";
    }
}

print CGI->end_table();

sub add_dur {
    my ($arr, $hr, $min) = @_;
    $arr->[2] += $min;
    while ($arr->[2] > 59) {
        $arr->[2] -= 60;
        $arr->[1]++;
    }
    $arr->[1] += $hr;
    while ($arr->[1] > 23) {
        $arr->[1] -= 24;
        $arr->[0]++;
    }
}

__DATA__
somebody   pts/93      1.2.3.4     Fri Mar 25 13:18 - 13:20  (00:02)
somebody   pts/94      1.2.3.5     Fri Mar 25 13:18 - 16:10  (00:52)
nobody   pts/94      1.2.3.5     Fri Mar 25 13:18 - 13:20  (00:00)

Open in new window

0
 

Author Comment

by:fac66
ID: 35437923
Thanks again!!
Working perfect so far
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Active Directory replication delay is the cause to many problems.  Here is a super easy script to force Active Directory replication to all sites with by using an elevated PowerShell command prompt, and a tool to verify your changes.
Q&A with Course Creator, Mark Lassoff, on the importance of HTML5 in the career of a modern-day developer.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …
Suggested Courses
Course of the Month15 days, 14 hours left to enroll

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question