in reply to Funky date question.

Not sure what you're asking for here.. but, again, here's what I thought it is:

my (@opn, @hold); while (my $line = <DATA>) { my ($_date, $id, $code) = split(/ \| /, $line); push @opn, $id if ($code =~ /open$/i); push @hold, $id if ($code =~ /hold$/i); } # do whatever you want with them now.. __DATA__ Date: Jan 1 2001 3:30PM | ID: 1 | Code: open Date: Jan 1 2001 3:35PM | ID: 1 | Code: open Date: Jan 1 2001 3:37PM | ID: 1 | Code: hold Date: Jan 1 2001 3:46PM | ID: 1 | Code: hold Date: Jan 1 2001 4:10PM | ID: 1 | Code: open Date: Jan 1 2001 4:35PM | ID: 1 | Code: hold

Update: I searched at CPAN, and found you might use DateTime-Precise


He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

Chady | http://chady.net/

Replies are listed 'Best First'.
Re: Re: Funky date question.
by Mark 1 (Initiate) on Jun 09, 2001 at 11:32 UTC
    Mabye I should restate the problem
    1 Date: Jan 1 2001 3:30PM | ID: 1 | Code: open 2 Date: Jan 1 2001 3:35PM | ID: 1 | Code: open 3 Date: Jan 1 2001 3:37PM | ID: 1 | Code: hold 4 Date: Jan 1 2001 3:46PM | ID: 1 | Code: hold 5 Date: Jan 1 2001 4:10PM | ID: 1 | Code: open 6 Date: Jan 1 2001 4:35PM | ID: 1 | Code: hold
    Im looking for time calculations, IE

    entries 1 and 2 are both open so thats 5 minutes open
    entries 3 and 4 are on hold, so we dont count that to our total
    entry 5 is open again and is open until entry 6 where it goes into hold again so thats 25 mins open there, in total a total of 30 mins the ID has been in 'open' code.

    Also, this is being pulled out of a sql database, so if theres any funky thing i can do with the database too would be informative.
      If I understand you correctly, it seems that you just need to define an extra variable that contains the basepoint for the current calculations. I'll try to demonstrate this is pseudocode here:
      my @currenttime=(); ## or initialize to the start time my @totaltime=(); ## will hold the sums for each ID foreach (@databaseline) { ## realistically, this will be something like ## while (@values = $sth->fetchrow) when you convert to ## using SQL ( Look at the DBI module and the corresponding ## DBD module for your database ) my ($dbtime,$code,$id)= &parseline($_); ## This routine would split the line and convert ## the date, passing back the useful values. ## When you get it out of SQL, you should have an array ## of values anyway, so it'll only be necessary to ## convert the date. $totaltime[$id]+=($dbtime-$currenttime[$id]) if $code eq 'open'; $currenttime[$id]=$dbtime; ## we move the baseline to the time of the current record } ## now the @totaltime array has the values you want.
        I have done somthing like this:
        my $dbh = DBI->connect("dbi:Sybase:server=CASTOR",$USER, $PASS); my $select = "select entrydate,status from database order by entry +date"; my $START = undef; my $STOP = undef; my $CUSTHOLD = 0; my $LASTSTATE=''; my $sth=$dbh->prepare($select); $sth->execute; while ( my $row = $sth->fetchrow_arrayref) { my ($entrydate,$statusid) = @$row; $LASTSTATE=$statusid; if ($statusid != "hold") { if($START) { $STOP = parse_date($entrydate); $CUSTHOLD += $STOP - $START; $START=undef; } } else { if (!$START) { $START = parse_date($entrydate); } } if(($LASTSTATE eq "hold") && defined $START) { $CUSTHOLD += time - $START; } } return($CUSTHOLD);
        the problem is some of my numbers come out obesly huge (and very wrong) and I cant quite figure out why.
Re: Re: Funky date question.
by Mark 1 (Initiate) on Jun 09, 2001 at 11:47 UTC
    The problem does not really lie in the 'how do I subtract this from this to get this', it lies in the logic behind the matter. 'how do I make my program so it does the math here, stops for a hold, and starts the math again when it goes out of hold'.

      Okay, I'll give this a shot; it appears you're looking for the logic, and not the code (which is good, because I'm not that good at Perl yet :). Anyway, here's my attempt at pseudocoding your problem:

      my ($starttime, $isopen, $totaltime) = (0, 0, 0); while (<TIMELOG>) { if (/open$/) { next if $isopen; $isopen = 1; $starttime = getseconds($_); } elsif (/hold$/ || /closed$/) { next unless $isopen; $isopen = 0; $totaltime += getseconds($_) - $starttime; } }

      Well, that came out a bit closer to code than I had intended... oh well. I hope that helps.

      Update: (1000 CDT 09 Jun) It occurred to me a bit more explanation might be in order. Basically, as I understand it, the key to your problem is to keep track of the first time you noticed the ID was in an open state, and only perform the addition to $totaltime when the ID moves out of the open state (and presumably, into one of the closed or hold states).

      Also, having watched a bit of the CB discussion on this topic, I noticed that you want to run this in realtime. If that's the case, you may want to generate a fake log entry to be processed at the end with the current time and a non-open state to force the calculation of the open time. This would change the code to be more like this:

      @lines = <TIMELOG>; push @lines, makefake(time(), "closed"); for (@lines) { # Same loop body }

      Update #2: Edited code and above comments on real time about current state.

      I know it might not be the optimal method to do it, but it seems as if it should get the job done (if I understand the job to be done correctly). Try it out - if it doesn't work, let me know. If it does, let me know then, too - I never know when I might need this bit of code. :)

      CheeseLord