bangor has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I am converting seconds to hours, minutes, seconds and this is how I have it:
sub parse_duration { my $seconds = shift; my $hours = int( $seconds / (60*60) ); my $mins = ( $seconds / 60 ) % 60; my $secs = $seconds % 60; return sprintf("%02d:%02d:%02d", $hours,$mins,$secs); }
This works, but i have to do this a lot of times and wonder if there is a faster way, like a single calculation rather than my three here. Thanks for any help.

Replies are listed 'Best First'.
Re: Convert time in seconds to hh::mm::ss
by 1nickt (Canon) on Mar 16, 2016 at 01:40 UTC

    Update: I saw in one of your replies that you only want hour:min:sec so my suggestion below is probably not what you want.

    Meanwhile I also found that an earlier monk has already benchmarked several solutions to this problem.

    You could use the core module Time::Seconds:

    #!/usr/bin/perl use strict; use warnings; use Time::Seconds; my $t = Time::Seconds->new( 12345678 ); print $t->pretty; __END__
    Output:
    142 days, 21 hours, 21 minutes, 18 seconds

    Hope this helps!


    The way forward always starts with a minimal test.

      It's always preferred to use core modules, but in this case, as opposed to the OP's sub, you'd have to create a new object per conversion (if my brief overview of the module has me understand it correctly):

      use warnings; use strict; use Benchmark qw(cmpthese); use Time::Seconds; my $time = '12345678'; cmpthese(1000000, { sub => "parse_duration('$time')", mod => "time_seconds('$time')", }); sub parse_duration { my $seconds = shift; my $hours = int( $seconds / (60*60) ); my $mins = ( $seconds / 60 ) % 60; my $secs = $seconds % 60; return sprintf("%02d:%02d:%02d", $hours,$mins,$secs); } sub time_seconds { my $seconds = shift; my $t = Time::Seconds->new($seconds); return $t->pretty; }

      Sometimes it's best just to keep it local:

      Rate mod sub mod 17819/s -- -95% sub 373134/s 1994% --

      kudos for the other day on the quoting of the var in my own bench, fwiw ;)

      - Hope this helps!

      That link really does help - thank you! Don't know how I didn't find that myself as was searching quite a bit - almost exactly the same title too.
Re: Convert time in seconds to hh::mm::ss
by bangor (Monk) on Mar 16, 2016 at 02:56 UTC
    From looking at the link provided by 1nickt I was able to double the speed for times less than 60 seconds (of which there are many) just by adding this line:
    return sprintf("00:00:%02d", $seconds) if $seconds < 60;

      Did that make any significant difference at all to the page fetch time?

      Benchmarking becomes interesting after profiling tells you where the significant hot spots are.

      Premature optimization is the root of all job security
Re: Convert time in seconds to hh::mm::ss
by Anonymous Monk on Mar 16, 2016 at 01:26 UTC

    This works, but i have to do this a lot of times and wonder if there is a faster way, like a single calculation rather than my three here. Thanks for any help.

    Did you measure how fast it takes?

    See Devel::Profile, and then promptly forget about speeding up parse_duration

      - Did you measure how fast it takes?

      No I didn't, that Devel::NYTProf looks one serious module - thanks. I do know how to use Benchmark but would be good if I had some other method to compare this with. Any examples I found wanted to convert to days, hours, etc. but I need to keep to hours only.

      edit - Oh, I see what you mean - should be no need to worry, that's good.

        If you know how to benchmark, and you know that there's no translation of DST etc involved, why bother doing premature profiling? Unless you're doing this thousands of times per second, I see nothing wrong with this simple sub.

        What exactly is the issue here?

Re: Convert time in seconds to hh::mm::ss
by Anonymous Monk on Mar 16, 2016 at 14:50 UTC

    Minor bump in speed can be obtained with use integer; Other than that, just keep your code as laconic as possible, avoiding temporary variables and statements:

    sub parse_duration { use integer; sprintf("%02d:%02d:%02d", $_[0]/3600, $_[0]/60%60, $_[0]%60); }