Loading ...
Sorry, an error occurred while loading the content.

Re: [PBML] Perl static var -- and a time warp...

Expand Messages
  • Jeff Eggen
    ... Did you try Date::Calc? It has handy Delta_**** functions for determining time & date differences, as well as functions for manipulating string
    Message 1 of 11 , Mar 9, 2004
    • 0 Attachment
      >>> allan_dystrup@... 03/09/04 02:17am >>>
      >And now to something completely different... A time warp!
      >The algorithm for the timeDiff above is... not very cool.
      >I tried :

      Did you try Date::Calc? It has handy Delta_**** functions for determining time & date differences, as well as functions for manipulating string representations of the date & time.

      Hope this helps,

      Jeff Eggen
      IT Programmer Analyst
      Saskatchewan Government Insurance
      Ph (306) 751-1795
      email jeggen@...
    • Allan Dystrup
      ... Thanks Charles, that neatly solved my problem! The Date::Calc (as suggested by Jeff Eggen) could have done the same, but was prob. overkill in this
      Message 2 of 11 , Mar 10, 2004
      • 0 Attachment
        >Charles K. Clarkson <cclarkson@h...> wrote:
        > return sprintf "%s:%s:%s", ( gmtime time - $sT )[ 2, 1, 0 ];

        Thanks Charles, that neatly solved my problem! The Date::Calc
        (as suggested by Jeff Eggen) could have done the same, but was
        prob. overkill in this specific situation.


        # TIMING
        #=====================================================================
        my $sT; # startTime
        sub timeStamp() {
        $sT = time; # 0 1 2 3 4 5 6
        7 8
        my @T = gmtime($sT); #
        ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
        my $yr = $T[5]+1900;
        my $mth = (qw(Jan Feb Mar Apr Maj Jun Jul Aug Sep Okt Nov Dec)) [$T
        [4]];
        my $day = (qw(Sun Mon Tue Wed Thu Fri Sat)) [$T[6]];
        return "$yr $mth.$T[3].$day $T[2]:$T[1]:$T[0]";
        }
        my $pT = time; # previousTime
        sub timeDiff() {
        my $diff = sprintf "Elapsed: %s:%s:%s", (gmtime time-$sT)[2,1,0]; #
        since $sT
        $diff .= sprintf " Delta: %s:%s:%s", (gmtime time-$pT)[2,1,0]; #
        since $pT
        $pT = time;
        return $diff;
        }
        #=====================================================================

        (As for using one-L RandaL's private vars as "my" own, --
        arrghh i'll think twice, next time ...:)

        thanks all
        allan
      • Charles K. Clarkson
        ... I realize that this is your adaptation of what I said, but you seem to have missed a couple of points. First, both subroutines should be wrapped in an
        Message 3 of 11 , Mar 11, 2004
        • 0 Attachment
          Allan Dystrup <allan_dystrup@...> wrote:
          :
          : >Charles K. Clarkson <cclarkson@h...> wrote:
          : > return sprintf "%s:%s:%s", ( gmtime time - $sT )[ 2, 1, 0 ];
          :
          : Thanks Charles, that neatly solved my problem! The Date::Calc
          : (as suggested by Jeff Eggen) could have done the same, but was
          : prob. overkill in this specific situation.

          I realize that this is your adaptation of what I said, but
          you seem to have missed a couple of points. First, both
          subroutines should be wrapped in an additional set of braces
          ( {} ) to allow only those subroutines to access $sT and $pT.


          Second, (and please don't take offense) why use a statement
          like this?

          my $sT; # startTime

          When this next one does the same thing and makes every use
          of the variable much more clear. No need for the comment or to
          look up to find out what $sT really means.

          my $start_time;

          (Sorry if I'm lecturing, but abbreviated variable names
          are a pet peeve.)


          Having said all that. Here's how I'd rewrite the time subs.

          {
          my $start_time;
          sub time_stamp() {
          $start_time = time;

          my( $day, $week_day, $month, $year, @time ) =
          ( gmtime $start_time )[3, 6, 4, 5, 2, 1, 0,];

          return
          sprintf "%s %s.%s.%s %s:%s:%s",
          $year + 1900,
          qw( Jan Feb Mar Apr Maj Jun Jul Aug Sep Okt Nov Dec )[
          $month ],
          $day,
          qw( Sun Mon Tue Wed Thu Fri Sat )[ $week_day ],
          @time;

          }

          my $previous_time = time;
          sub timeDiff() {
          my $diff =
          sprintf "Elapsed: %s:%s:%s",
          ( gmtime time - $start_time )[2,1,0];

          $diff .=
          sprintf " Delta: %s:%s:%s",
          ( gmtime time - $previous_time )[2,1,0];

          $previous_time = time;
          return $diff;
          }
          }


          Unfortunately, it's wrong.

          Why?

          Perl doesn't know when we need "my $previous_time = time;"
          to be handled and there is a logic error. This results in an
          uninitialized value error when the program runs.

          The first problem can be solved by using BEGIN before the
          outer block. But then a logic error creeps in. We'll test it
          to demonstrate the error. Here's a test program. The first
          'sleep 2;' simulates the start up of the program. (Note: I
          left off the prototyping '()' on the subroutines definitions.)

          #!/usr/bin/perl

          use strict;
          use warnings;

          # turn off buffering
          $| = 1;

          # add \n to print
          $\ = "\n";

          sleep 2;
          print time_stamp();
          sleep 1;
          print timeDiff();
          sleep 1;
          print timeDiff();

          BEGIN {
          my $start_time;
          sub time_stamp {
          $start_time = time;

          my( $day, $week_day, $month, $year, @time ) =
          ( gmtime $start_time )[3, 6, 4, 5, 2, 1, 0,];

          return
          sprintf "%s %s.%s.%s %s:%s:%s",
          $year + 1900,
          qw( Jan Feb Mar Apr Maj Jun Jul Aug Sep Okt Nov Dec )[
          $month ],
          $day,
          qw( Sun Mon Tue Wed Thu Fri Sat )[ $week_day ],
          @time;

          }

          my $previous_time = time;
          sub timeDiff {
          my $diff =
          sprintf "Elapsed: %s:%s:%s",
          ( gmtime time - $start_time )[2,1,0];

          $diff .=
          sprintf " Delta: %s:%s:%s",
          ( gmtime time - $previous_time )[2,1,0];

          $previous_time = time;
          return $diff;
          }
          }

          __END__

          Here's what I get:

          2004 Mar.11.Thu 13:24:36
          Elapsed: 0:0:1 Delta: 0:0:3
          Elapsed: 0:0:2 Delta: 0:0:1

          Notice that the Delta time is larger than the
          Elapsed time on the first line. That accounts for
          the first sleep statement.

          We can solve this by testing for the first run
          of timeDiff().

          my $previous_time;
          sub timeDiff {

          # On first pass set default to $start_time
          $previous_time ||= $start_time;

          my $diff =
          sprintf "Elapsed: %s:%s:%s",
          ( gmtime time - $start_time )[2,1,0];

          $diff .=
          sprintf " Delta: %s:%s:%s",
          ( gmtime time - $previous_time )[2,1,0];

          $previous_time = time;
          return $diff;
          }


          Okay, everything seems fine, until I port your
          program to my XP system. I find your script so
          useful that I run it as a service. Unfortunately,
          I sometimes get this result:

          2004 Mar.11.Thu 13:42:26
          Elapsed: 0:0:1 Delta: 0:0:2
          Elapsed: 0:0:3 Delta: 0:0:2


          Why?

          Because my service is sometimes interrupted by
          other programs that are running and the time()
          used in "gmtime time - $start_time" differs from
          that returned in "gmtime time - $previous_time".
          This is a highly unlikely, but plausible
          circumstance. We are computer programmers. Our
          solutions should work all the time.

          Here's my solution:

          my $previous_time;
          sub timeDiff {
          # $start_time on first pass
          $previous_time ||= $start_time;

          my $now = time;

          my $diff =
          sprintf "Elapsed: %s:%s:%s",
          ( gmtime $now - $start_time )[2,1,0];

          $diff .=
          sprintf " Delta: %s:%s:%s",
          ( gmtime $now - $previous_time )[2,1,0];

          $previous_time = $now;
          return $diff;
          }


          So everything is humming along just fine, until
          May 2. On that day I look at the my logs and find
          all the dates say Maj instead of May. WTF?

          Closer examination of the script reveals this
          line in time_stamp():

          qw( Jan Feb Mar Apr Maj Jun Jul Aug Sep Okt Nov Dec )[ $month ],

          Obviously, whoever wrote the original script was
          in a locale that use "Maj" and "Okt" as abbreviations
          for "May" and "Oct". No problem. I'll just change
          this line in each of the two thousand locations I
          have it installed. Too bad the original programmer
          didn't use a locale sensitive function.

          How can we fix this one?

          Well, some of the conversion specifications of the
          POSIX function 'stftime()' are locale sensitive. Here's
          a new solution for time_stamp().

          use POSIX 'strftime';
          my $start_time;
          sub time_stamp {
          $start_time = time;
          return strftime '%Y %b.%d.%a %H:%M:%S', gmtime $start_time;
          }

          Here's what I ended up with. I wonder if I missed
          anything else.

          BEGIN {
          use POSIX 'strftime';
          my $start_time;
          my $previous_time;

          sub time_stamp {
          $start_time = time;
          return strftime '%Y %b.%d.%a %H:%M:%S', gmtime $start_time;
          }

          sub timeDiff {
          # $start_time on first pass
          $previous_time ||= $start_time;

          my $now = time;
          my $elapsed = strftime '%H:%M:%S', gmtime $now - $start_time;
          my $delta = strftime '%H:%M:%S', gmtime $now - $previous_time;

          $previous_time = $now;

          return sprintf "Elapsed: %s Delta: %s", $elapsed, $delta;
          }
          }


          Maybe Date::Calc isn't overkill after all!


          HTH,

          Charles K. Clarkson
          --
          Mobile Homes Specialist
          254 968-8328
        • merlyn@stonehenge.com
          ... Charles BEGIN { Charles use POSIX strftime ; Charles my $start_time; Charles my $previous_time; Charles sub time_stamp { Charles
          Message 4 of 11 , Mar 11, 2004
          • 0 Attachment
            >>>>> "Charles" == Charles K Clarkson <cclarkson@...> writes:

            Charles> BEGIN {
            Charles> use POSIX 'strftime';
            Charles> my $start_time;
            Charles> my $previous_time;

            Charles> sub time_stamp {
            Charles> $start_time = time;
            Charles> return strftime '%Y %b.%d.%a %H:%M:%S', gmtime $start_time;
            Charles> }

            Charles> sub timeDiff {
            Charles> # $start_time on first pass
            Charles> $previous_time ||= $start_time;

            Charles> my $now = time;
            Charles> my $elapsed = strftime '%H:%M:%S', gmtime $now - $start_time;
            Charles> my $delta = strftime '%H:%M:%S', gmtime $now - $previous_time;

            Charles> $previous_time = $now;

            Charles> return sprintf "Elapsed: %s Delta: %s", $elapsed, $delta;
            Charles> }
            Charles> }


            Charles> Maybe Date::Calc isn't overkill after all!

            Why store $start_time as a strftime though? Just store it as an epoch
            timestamp, and then datecalcs are trivial.

            Here's code that keeps track of delta times for its call:

            BEGIN {
            my $prev = time;

            sub elapsed {
            my $new = time;
            my $diff = $new - $prev;
            $prev = $new; # set new baseline
            return $diff;
            }
            }

            Now, calls to elapsed() return the delta between calls as a number
            of seconds (which the caller can format as sees fit), or between
            that call and the initial compile of the program.

            --
            Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
            <merlyn@...> <URL:http://www.stonehenge.com/merlyn/>
            Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
            See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
          • Jeff Eggen
            ... Vindication!! Thanks Charles ! ;-) Seriously though, to those who believe Date::Calc (and other multi-purpose modules) to be overkill for your current
            Message 5 of 11 , Mar 11, 2004
            • 0 Attachment
              >>> cclarkson@... 03/11/04 08:47am >>>
              > Maybe Date::Calc isn't overkill after all!

              Vindication!! Thanks Charles ! ;-)

              Seriously though, to those who believe Date::Calc (and other multi-purpose modules) to be overkill for your current need: perhaps you should be looking at the module and instead of thinking "This thing has way more functionality than I need", you should be thinking "This thing has something I need now, and I can see a lot of other functionality that could come in useful down the road". I originally downloaded & installed Date::Calc for a single purpose because I didn't feel like coding up something that figured up the difference between two dates in days (laziness is one of the three main virtues, right?). But thanks to having it around I've offered it up to other people as a super easy solution for various date & time programming problems where people were bent on coming up with their own solution. Besides which, date & time calculations have so many bizarre subtleties and nuances (take leap year calculation for an easy example) that home-grown solutions can easily contain subtle errors that won't show up for some time.

              Long story short: I can respect your desire to come up with your own solution for whatever the reason, but a better solution is often just a CPAN search away. Just something to think about.



              Jeff Eggen
              IT Programmer Analyst
              Saskatchewan Government Insurance
              Ph (306) 751-1795
              email jeggen@...
            • Leon
              ... __________________________________ Do you Yahoo!? Yahoo! Search - Find what you’re looking for faster http://search.yahoo.com
              Message 6 of 11 , Mar 11, 2004
              • 0 Attachment
                --- Jeff Eggen <jeggen@...> wrote:
                > >>> cclarkson@... 03/11/04 08:47am >>>
                > > Maybe Date::Calc isn't overkill after all!
                >
                > Vindication!! Thanks Charles ! ;-)
                >
                > Seriously though, to those who believe Date::Calc
                > (and other multi-purpose modules) to be overkill for
                > your current need: perhaps you should be looking at
                > the module and instead of thinking "This thing has
                > way more functionality than I need", you should be
                > thinking "This thing has something I need now, and I
                > can see a lot of other functionality that could come
                > in useful down the road". I originally downloaded &
                > installed Date::Calc for a single purpose because I
                > didn't feel like coding up something that figured up
                > the difference between two dates in days (laziness
                > is one of the three main virtues, right?). But
                > thanks to having it around I've offered it up to
                > other people as a super easy solution for various
                > date & time programming problems where people were
                > bent on coming up with their own solution. Besides
                > which, date & time calculations have so many bizarre
                > subtleties and nuances (take leap year calculation
                > for an easy example) that home-grown solutions can
                > easily contain subtle errors that won't show up for
                > some time.
                >
                > Long story short: I can respect your desire to come
                > up with your own solution for whatever the reason,
                > but a better solution is often just a CPAN search
                > away. Just something to think about.
                >
                >
                >
                > Jeff Eggen
                > IT Programmer Analyst
                > Saskatchewan Government Insurance
                > Ph (306) 751-1795
                > email jeggen@...
                >
                >


                __________________________________
                Do you Yahoo!?
                Yahoo! Search - Find what you�re looking for faster
                http://search.yahoo.com
              • merlyn@stonehenge.com
                ... Jeff Seriously though, to those who believe Date::Calc Rather than Date::Calc, for new coding you should look at the ever-increasing family of DateTime
                Message 7 of 11 , Mar 11, 2004
                • 0 Attachment
                  >>>>> "Jeff" == Jeff Eggen <jeggen@...> writes:

                  Jeff> Seriously though, to those who believe Date::Calc

                  Rather than Date::Calc, for new coding you should look at the
                  ever-increasing family of DateTime modules. The work is moving along
                  nicely, documented at datetime.perl.org.

                  More than likely, you'll find exactly the conversion or calculation
                  you need.
                  --
                  Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
                  <merlyn@...> <URL:http://www.stonehenge.com/merlyn/>
                  Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
                  See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
                • Jeff Eggen
                  ... Is there, then, going to be some universally accepted standard module for date & time manipulations? The number of date & time related modules on cpan is
                  Message 8 of 11 , Mar 11, 2004
                  • 0 Attachment
                    >>> merlyn@... 03/11/04 11:34am >>>
                    >Rather than Date::Calc, for new coding you should look at the
                    >ever-increasing family of DateTime modules. The work is moving along
                    >nicely, documented at datetime.perl.org.

                    >More than likely, you'll find exactly the conversion or calculation
                    >you need.

                    Is there, then, going to be some universally accepted standard module for date & time manipulations? The number of date & time related modules on cpan is kind of rediculous. Is the DateTime family going to be this standard? I know I read something a while ago where module authors were complaining about the amount of over(lap|kill) for date & time, and talk of combining all this functionality into one specific package or bundle was under way.

                    I'll check out datetime.perl.org. Thanks for the reference!

                    Jeff Eggen
                    IT Programmer Analyst
                    Saskatchewan Government Insurance
                    Ph (306) 751-1795
                    email jeggen@...
                  • merlyn@stonehenge.com
                    ... Jeff Is there, then, going to be some universally accepted standard Jeff module for date & time manipulations? The number of date & time Jeff related
                    Message 9 of 11 , Mar 11, 2004
                    • 0 Attachment
                      >>>>> "Jeff" == Jeff Eggen <jeggen@...> writes:

                      Jeff> Is there, then, going to be some universally accepted standard
                      Jeff> module for date & time manipulations? The number of date & time
                      Jeff> related modules on cpan is kind of rediculous. Is the DateTime
                      Jeff> family going to be this standard?

                      Well, it has the most momentum and buzz, so I presume it will be.
                      There's been dozens of releases of DateTime::* modules in the space
                      since the last update of Date::Calc or Date::Manip, for example.

                      Jeff> I know I read something a
                      Jeff> while ago where module authors were complaining about the amount
                      Jeff> of over(lap|kill) for date & time, and talk of combining all
                      Jeff> this functionality into one specific package or bundle was under
                      Jeff> way.

                      Yes, that's DateTime!

                      --
                      Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
                      <merlyn@...> <URL:http://www.stonehenge.com/merlyn/>
                      Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
                      See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
                    • Charles K. Clarkson
                      ... Actually it is stored as an epoch. It is returned as strftime. The subroutines are meant to be compatible with those Allan originally presented. ...
                      Message 10 of 11 , Mar 12, 2004
                      • 0 Attachment
                        Randal L. Schwartz <merlyn@...> wrote:
                        :
                        : >>>>> "Charles" == Charles K Clarkson <cclarkson@...> writes:
                        :
                        : Charles> BEGIN {
                        : Charles> use POSIX 'strftime';
                        : Charles> my $start_time;
                        : Charles> my $previous_time;
                        :
                        : Charles> sub time_stamp {
                        : Charles> $start_time = time;
                        : Charles> return strftime '%Y %b.%d.%a %H:%M:%S',
                        : Charles> gmtime $start_time;
                        : Charles> }
                        :
                        : Charles> sub timeDiff {
                        : Charles> # $start_time on first pass
                        : Charles> $previous_time ||= $start_time;
                        :
                        : Charles> my $now = time;
                        : Charles> my $elapsed = strftime '%H:%M:%S',
                        : Charles> gmtime $now - $start_time;
                        : Charles> my $delta = strftime '%H:%M:%S',
                        : Charles> gmtime $now - $previous_time;
                        :
                        : Charles> $previous_time = $now;
                        :
                        : Charles> return sprintf "Elapsed: %s Delta: %s",
                        : Charles> $elapsed, $delta;
                        : Charles> }
                        : Charles> }
                        :
                        : Why store $start_time as a strftime though? Just store it as an
                        : epoch timestamp, and then date calcs are trivial.

                        Actually it is stored as an epoch. It is returned as strftime.
                        The subroutines are meant to be compatible with those Allan
                        originally presented.


                        : Here's code that keeps track of delta times for its call:
                        :
                        : BEGIN {
                        : my $prev = time;
                        :
                        : sub elapsed {
                        : my $new = time;
                        : my $diff = $new - $prev;
                        : $prev = $new; # set new baseline
                        : return $diff;
                        : }
                        : }
                        :
                        : Now, calls to elapsed() return the delta between calls as a number
                        : of seconds (which the caller can format as sees fit),

                        Shouldn't we then call it delta()? :)


                        : or between that call and the initial compile of the program.

                        The original functions were presented with formats already in
                        place. I understand what you are saying about elapsed(), but you are
                        assuming the caller wants to do the formatting /outside/ the sub. Of
                        course, I'm assuming the caller wants a formatted output. Without
                        Allan's input we are both guessing.


                        HTH,

                        Charles K. Clarkson
                        --
                        Mobile Homes Specialist
                        254 968-8328
                      • Allan Dystrup
                        Hi Charles, Before this fine mails scrolls into the big bit bucket, i just wanted to thank you for the timely && (en)lightening reminder of the value of
                        Message 11 of 11 , Mar 14, 2004
                        • 0 Attachment
                          Hi Charles,

                          Before this fine mails scrolls into the big bit bucket, i just wanted
                          to thank you for the timely && (en)lightening reminder of the value
                          of generalization and precision, in calculation as in programming
                          style.

                          My next stop on the Path-of-Perl will be digging into CPAN and the
                          modules available there.

                          Tnx, allan


                          --- In perl-beginner@yahoogroups.com, "Charles K. Clarkson"
                          <cclarkson@h...> wrote:
                          > Allan Dystrup <allan_dystrup@y...> wrote:
                          > :
                          > : >Charles K. Clarkson <cclarkson@h...> wrote:
                          > : > return sprintf "%s:%s:%s", ( gmtime time - $sT )[ 2, 1, 0 ];
                          > :
                          > : Thanks Charles, that neatly solved my problem! The Date::Calc
                          > : (as suggested by Jeff Eggen) could have done the same, but was
                          > : prob. overkill in this specific situation.
                          >
                          > I realize that this is your adaptation of what I said, but
                          > you seem to have missed a couple of points. First, both
                          > subroutines should be wrapped in an additional set of braces
                          > ( {} ) to allow only those subroutines to access $sT and $pT.
                          >
                          >
                          > Second, (and please don't take offense) why use a statement
                          > like this?
                          >
                          > my $sT; # startTime
                          >
                          > When this next one does the same thing and makes every use
                          > of the variable much more clear. No need for the comment or to
                          > look up to find out what $sT really means.
                          >
                          > my $start_time;
                          >
                          > (Sorry if I'm lecturing, but abbreviated variable names
                          > are a pet peeve.)
                          >
                          >
                          > Having said all that. Here's how I'd rewrite the time subs.
                          >
                          > {
                          > my $start_time;
                          > sub time_stamp() {
                          > $start_time = time;
                          >
                          > my( $day, $week_day, $month, $year, @time ) =
                          > ( gmtime $start_time )[3, 6, 4, 5, 2, 1, 0,];
                          >
                          > return
                          > sprintf "%s %s.%s.%s %s:%s:%s",
                          > $year + 1900,
                          > qw( Jan Feb Mar Apr Maj Jun Jul Aug Sep Okt Nov
                          Dec )[
                          > $month ],
                          > $day,
                          > qw( Sun Mon Tue Wed Thu Fri Sat )[ $week_day ],
                          > @time;
                          >
                          > }
                          >
                          > my $previous_time = time;
                          > sub timeDiff() {
                          > my $diff =
                          > sprintf "Elapsed: %s:%s:%s",
                          > ( gmtime time - $start_time )[2,1,0];
                          >
                          > $diff .=
                          > sprintf " Delta: %s:%s:%s",
                          > ( gmtime time - $previous_time )[2,1,0];
                          >
                          > $previous_time = time;
                          > return $diff;
                          > }
                          > }
                          >
                          >
                          > Unfortunately, it's wrong.
                          >
                          > Why?
                          >
                          > Perl doesn't know when we need "my $previous_time = time;"
                          > to be handled and there is a logic error. This results in an
                          > uninitialized value error when the program runs.
                          >
                          > The first problem can be solved by using BEGIN before the
                          > outer block. But then a logic error creeps in. We'll test it
                          > to demonstrate the error. Here's a test program. The first
                          > 'sleep 2;' simulates the start up of the program. (Note: I
                          > left off the prototyping '()' on the subroutines definitions.)
                          >
                          > #!/usr/bin/perl
                          >
                          > use strict;
                          > use warnings;
                          >
                          > # turn off buffering
                          > $| = 1;
                          >
                          > # add \n to print
                          > $\ = "\n";
                          >
                          > sleep 2;
                          > print time_stamp();
                          > sleep 1;
                          > print timeDiff();
                          > sleep 1;
                          > print timeDiff();
                          >
                          > BEGIN {
                          > my $start_time;
                          > sub time_stamp {
                          > $start_time = time;
                          >
                          > my( $day, $week_day, $month, $year, @time ) =
                          > ( gmtime $start_time )[3, 6, 4, 5, 2, 1, 0,];
                          >
                          > return
                          > sprintf "%s %s.%s.%s %s:%s:%s",
                          > $year + 1900,
                          > qw( Jan Feb Mar Apr Maj Jun Jul Aug Sep Okt Nov
                          Dec )[
                          > $month ],
                          > $day,
                          > qw( Sun Mon Tue Wed Thu Fri Sat )[ $week_day ],
                          > @time;
                          >
                          > }
                          >
                          > my $previous_time = time;
                          > sub timeDiff {
                          > my $diff =
                          > sprintf "Elapsed: %s:%s:%s",
                          > ( gmtime time - $start_time )[2,1,0];
                          >
                          > $diff .=
                          > sprintf " Delta: %s:%s:%s",
                          > ( gmtime time - $previous_time )[2,1,0];
                          >
                          > $previous_time = time;
                          > return $diff;
                          > }
                          > }
                          >
                          > __END__
                          >
                          > Here's what I get:
                          >
                          > 2004 Mar.11.Thu 13:24:36
                          > Elapsed: 0:0:1 Delta: 0:0:3
                          > Elapsed: 0:0:2 Delta: 0:0:1
                          >
                          > Notice that the Delta time is larger than the
                          > Elapsed time on the first line. That accounts for
                          > the first sleep statement.
                          >
                          > We can solve this by testing for the first run
                          > of timeDiff().
                          >
                          > my $previous_time;
                          > sub timeDiff {
                          >
                          > # On first pass set default to $start_time
                          > $previous_time ||= $start_time;
                          >
                          > my $diff =
                          > sprintf "Elapsed: %s:%s:%s",
                          > ( gmtime time - $start_time )[2,1,0];
                          >
                          > $diff .=
                          > sprintf " Delta: %s:%s:%s",
                          > ( gmtime time - $previous_time )[2,1,0];
                          >
                          > $previous_time = time;
                          > return $diff;
                          > }
                          >
                          >
                          > Okay, everything seems fine, until I port your
                          > program to my XP system. I find your script so
                          > useful that I run it as a service. Unfortunately,
                          > I sometimes get this result:
                          >
                          > 2004 Mar.11.Thu 13:42:26
                          > Elapsed: 0:0:1 Delta: 0:0:2
                          > Elapsed: 0:0:3 Delta: 0:0:2
                          >
                          >
                          > Why?
                          >
                          > Because my service is sometimes interrupted by
                          > other programs that are running and the time()
                          > used in "gmtime time - $start_time" differs from
                          > that returned in "gmtime time - $previous_time".
                          > This is a highly unlikely, but plausible
                          > circumstance. We are computer programmers. Our
                          > solutions should work all the time.
                          >
                          > Here's my solution:
                          >
                          > my $previous_time;
                          > sub timeDiff {
                          > # $start_time on first pass
                          > $previous_time ||= $start_time;
                          >
                          > my $now = time;
                          >
                          > my $diff =
                          > sprintf "Elapsed: %s:%s:%s",
                          > ( gmtime $now - $start_time )[2,1,0];
                          >
                          > $diff .=
                          > sprintf " Delta: %s:%s:%s",
                          > ( gmtime $now - $previous_time )[2,1,0];
                          >
                          > $previous_time = $now;
                          > return $diff;
                          > }
                          >
                          >
                          > So everything is humming along just fine, until
                          > May 2. On that day I look at the my logs and find
                          > all the dates say Maj instead of May. WTF?
                          >
                          > Closer examination of the script reveals this
                          > line in time_stamp():
                          >
                          > qw( Jan Feb Mar Apr Maj Jun Jul Aug Sep Okt Nov Dec )[ $month ],
                          >
                          > Obviously, whoever wrote the original script was
                          > in a locale that use "Maj" and "Okt" as abbreviations
                          > for "May" and "Oct". No problem. I'll just change
                          > this line in each of the two thousand locations I
                          > have it installed. Too bad the original programmer
                          > didn't use a locale sensitive function.
                          >
                          > How can we fix this one?
                          >
                          > Well, some of the conversion specifications of the
                          > POSIX function 'stftime()' are locale sensitive. Here's
                          > a new solution for time_stamp().
                          >
                          > use POSIX 'strftime';
                          > my $start_time;
                          > sub time_stamp {
                          > $start_time = time;
                          > return strftime '%Y %b.%d.%a %H:%M:%S', gmtime $start_time;
                          > }
                          >
                          > Here's what I ended up with. I wonder if I missed
                          > anything else.
                          >
                          > BEGIN {
                          > use POSIX 'strftime';
                          > my $start_time;
                          > my $previous_time;
                          >
                          > sub time_stamp {
                          > $start_time = time;
                          > return strftime '%Y %b.%d.%a %H:%M:%S', gmtime $start_time;
                          > }
                          >
                          > sub timeDiff {
                          > # $start_time on first pass
                          > $previous_time ||= $start_time;
                          >
                          > my $now = time;
                          > my $elapsed = strftime '%H:%M:%S', gmtime $now -
                          $start_time;
                          > my $delta = strftime '%H:%M:%S', gmtime $now -
                          $previous_time;
                          >
                          > $previous_time = $now;
                          >
                          > return sprintf "Elapsed: %s Delta: %s", $elapsed, $delta;
                          > }
                          > }
                          >
                          >
                          > Maybe Date::Calc isn't overkill after all!
                          >
                          >
                          > HTH,
                          >
                          > Charles K. Clarkson
                          > --
                          > Mobile Homes Specialist
                          > 254 968-8328
                        Your message has been successfully submitted and would be delivered to recipients shortly.