Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re: Timer subtraction (updated)

by haukex (Abbot)
on Oct 06, 2017 at 08:57 UTC ( #1200808=note: print w/replies, xml ) Need Help??


in reply to Timer subtraction

I normally use the DateTime family of modules for this kind of thing. It looks like what you have there are not absolute times, but timer durations, in which case you could try working with DateTime::Duration objects. (If you are instead working with absolute times, see here and here for solutions.)

I looked into how to parse durations, and found DateTime::Format::Duration, but am having trouble getting it to parse milliseconds - I have a suspicion this may be a bug, and will look into this and update my node when I know more (Update: Bug reported.). Until then, parsing the duration manually seems to work, as follows. By the way, is it a typo that your milliseconds in $first only have two digits?

Update 2018-01-15: I have to withdraw my suggestion for DateTime::Format::Duration for now, the number of unfixed bugs - including the one reported by Cristoforo in the reply - is leading me to believe that the module is currently suffering from too many issues to be "just used". See my reply below for a quick-n-dirty alternative, although unfortunately that doesn't support normalization.

use warnings; use strict; use DateTime::Duration; use DateTime::Format::Duration; my $first = "00:00:01:04"; my $last = "00:00:08:861"; sub my_parse_duration { my $in = shift; my %t; @t{qw/hours minutes seconds nanoseconds/} = $in=~/\A(\d\d):(\d\d):(\d\d):(\d\d\d?)\z/ or die "failed to parse '$in'"; $t{nanoseconds}*=1000000; # ms->ns return DateTime::Duration->new(%t); } $first = my_parse_duration($first); $last = my_parse_duration($last ); my $fmt_out = DateTime::Format::Duration->new( pattern=>'%H:%M:%S:%3N', normalize=>1 ); print $fmt_out->format_duration($first),"\n"; print $fmt_out->format_duration($last ),"\n"; $last->subtract_duration($first); print $fmt_out->format_duration($last ),"\n"; __END__ 00:00:01:004 00:00:08:861 00:00:07:857

Replies are listed 'Best First'.
Re^2: Timer subtraction
by Cristoforo (Curate) on Jan 14, 2018 at 23:00 UTC
    Hi haukex,

    I was using your code and found a problem with different duration parameters.

    my $first = "01:25:52:421"; my $last = "01:26:29:369";
    For this example the seconds and milliseconds in the $last variable have lesser amounts than in the $first variable. The program hangs and will not complete. It only executes the first two print statements. The result should be 00:00:36:948.

    I don't know what can be done to get the program to run to completion (and execute the third print).

    I've been working on this for several days, reading the docs for DateTime::Format::Duration and can't find the answer there - maybe I don't understand it well.

Re^2: Timer subtraction
by Anonymous Monk on Oct 06, 2017 at 09:21 UTC

    Thanks. Format duration is not working for me. In the last 3 print statements you are using format_duration which is not supported. Unfortunately, your code snippet fails. Yes, millisecs specified above was typo

      Format duration is not working for me. In the last 3 print statements you are using format_duration which is not supported. Unfortunately, your code snippet fails.

      The code snippet works fine for me. How does it fail for you? Please see How do I post a question effectively? and I know what I mean. Why don't you? - what are the exact error messages you get? Perhaps you have to install DateTime::Format::Duration?

      Even if not, you can still access the fields of the DateTime::Duration object yourself. This outputs the same thing as my above code:

      sub my_fmt_duration { my @t = shift->in_units('hours','minutes','seconds','nanoseconds') +; $t[3]/=1000000; # ns->ms return sprintf("%02d:%02d:%02d:%03d",@t); } print my_fmt_duration($first),"\n"; print my_fmt_duration($last ),"\n"; $last->subtract_duration($first); print my_fmt_duration($last ),"\n";

        Thank you. It worked

        #!/volume/perl/bin/perl use warnings; use strict; use DateTime::Duration; my $first = "00:00:01:04"; my $last = "00:00:08:861"; sub my_parse_duration { my $in = shift; my %t; @t{qw/hours minutes seconds nanoseconds/} = $in=~/\A(\d\d):(\d\d):(\d\d):(\d\d\d?)\z/ or die "failed to parse '$in'"; $t{nanoseconds}*=1000000; # ms->ns return DateTime::Duration->new(%t); } sub my_fmt_duration { my @t = shift->in_units('hours','minutes','seconds','nanoseconds') +; $t[3]/=1000000; # ns->ms return sprintf("%02d:%02d:%02d:%03d",@t); } $first = my_parse_duration($first); $last = my_parse_duration($last ); $last->subtract_duration($first); print my_fmt_duration($last ),"\n";

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1200808]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (6)
As of 2018-07-16 01:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?















    Results (330 votes). Check out past polls.

    Notices?