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

how can I eassily increment hh:mm:ss by a specified number of seconds? at the moment my script converts hh:mm:ss to seconds then adds seconds on then convert back to hh:mm:ss format. I can't help thinking there is a much better way of doind this.
$current_time="00:02:25"; @stime = split(/:/, $current_time); $current_time_more10s = 3600*$stime[0] + 60*$stime[1] + $stime[2]; $current_time_more10s=$current_time_more10s+10; $hours=($current_time_more10s/(60*60))%24;if($hours<10){$hours="0$hour +s";} $mins=($current_time_more10s/60)%60;if($mins<10){$mins="0$mins";} $secs=$current_time_more10s%60;if($secs<10){$secs="0$secs";} $newtime="$hours:$mins:$secs"; print $newtime;

Replies are listed 'Best First'.
Re: increment hh:mm:ss
by belg4mit (Prior) on Jan 26, 2002 at 23:55 UTC
    Isn't this what Date::Calc is for? It also seems that if you wanted roll your own you could convert back to epoch (with POSIX), add seconds, and the do localtime on the result.

    UPDATE</b: Upon further inspection the premise of my roll-your-own is similar to what you are doing, I approve ;-). However I believe the suggestion meets your requirement of simplifying the process, YMMV.

    --
    perl -pe "s/\b;([st])/'\1/mg"

Re: increment hh:mm:ss
by jonjacobmoon (Pilgrim) on Jan 27, 2002 at 00:52 UTC
    Although, Date::Calc is a good one to use, I have started using Class::Date because the interface is a little easier. I can't remember the syntax off-hand and haven't the time right now to look it up, but basically all you do is create a date object formatted the way you want and then add the seconds. Something like:
    $date = date(<PUT YOUR FORMAT HERE>) # create new date object $seonds = $num_secs . "s"; $date += $seconds

    I think it should be that simple. Sorry I am being so vague here, but the Class::Date docs are pretty good and will no doubt enlighten you better than I have.


    I admit it, I am Paco.
Re: increment hh:mm:ss
by dws (Chancellor) on Jan 27, 2002 at 00:16 UTC
    at the moment my script converts hh:mm:ss to seconds then adds seconds on then convert back to hh:mm:ss format.

    Caveat:

    Unless you're using GMT, or are working within a time zone that does not honor daylight savings time, doing simple math on raw time components will give you the wrong results during two one-hour windows each year.

    Since the daylight savings switch happens at 1-2am, this might not be an issue to you. But do be aware.

    Using one of the various Data/Time packages is safer.

Re: increment hh:mm:ss
by nandeya (Monk) on Jan 27, 2002 at 06:14 UTC
    Here's a quick ex. with the aforementioned Date::Calc.

    use strict; use Date::Calc; my ($year,$month,$day, $hour,$min,$sec) = Date::Calc::Today_and_Now(); my $addDays=0; my $addHours=0; my $addMins=0; my $addSecs=10; my ($nyear,$nmonth,$nday,$nhour,$nmin,$nsec) = Date::Calc::Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec, $addDays,$addHours,$addMins,$addSecs); print "Now : $month/$day/$year $hour:$min:$sec \n"; print "Now + 10 secs: $nmonth/$nday/$nyear $nhour:$nmin:$nsec \n";

    nandeya
Re: increment hh:mm:ss
by Aristotle (Chancellor) on Jan 26, 2002 at 23:27 UTC
    my $current_time="00:02:25"; my $time_inc = 10; my ($h, $m, $s) = split(/:/, $current_time); $s += $time_inc; ### 1 ### $m += int($s / 60); ### 2 ### $s %= 60; ### 3 ### $h += int($m / 60); $m %= 60; my $new_time = join ':', $h, $m, $s; print "$new_time\n";

    What we do is increase the seconds without caring about the overflow at first (see 1.) - the result may well go over 60. Then we increase the minutes by the nonfractional part of seconds / 60 (see 2.) and set the seconds to the remainder of seconds / 60 (see 3.). Since the minutes may have gone over 60 we repeat the same process there, adding the overflow to the hours. Finally we join the values with double colons and print the result.

    Update: My bad. Listen to belg4mit. I would suggest a look at Time::Local instead though - since that comes bundled with Perl.

    Makeshifts last the longest.

Using Time::Piece to increment hh:mm:ss
by blakem (Monsignor) on Jan 27, 2002 at 07:31 UTC
    Time::Piece is cool.....
    #!/usr/bin/perl -wT use strict; use Time::Piece; my $time = "10:30:05"; my $delta = 1000; my $newtime = deltatime($time,$delta); print "$time + $delta => $newtime\n"; sub deltatime { my $t = Time::Piece->strptime(shift,"%T") + shift; return $t->strftime("%T"); }
    Or, as a one liner....
    perl -MTime::Piece -le'print+(Time::Piece->strptime(pop,"%T")+pop)->st +rftime("%T")' 1000 10:30:05

    -Blake

Re: increment hh:mm:ss
by theguvnor (Chaplain) on Jan 27, 2002 at 00:11 UTC
    Why not generalise this a bit, to a subroutine that can adjust a given time by a given number of seconds? And rather than using an if to determine whether you need to pad the hours with a leading 0, use sprintf to format the integer to a 2-digit string like so:

    #!/usr/bin/perl $now = '00:00:00'; for (0..60*60*24+5) { print adjust_time($now, $_), "\n"; } exit; sub adjust_time { my $start_time = shift; my $increment = shift; my ($hour, $min, $sec) = split /:/, $start_time; my $seconds = 3600 * $hour + 60 * $min + $sec; $seconds += $increment; $hour = sprintf "%02d", ($seconds/3600) % 12; # add + 1 here for 1 +2 hour format; $min = sprintf "%02d", ($seconds/60) % 60; $sec = sprintf "%02d", $seconds % 60; return "$hour:$min:$sec"; }
Re: increment hh:mm:ss
by gav^ (Curate) on Jan 26, 2002 at 23:32 UTC
    my $secs = 60; my $time = '23:59:25'; my @time = split /:/, $time, 3; $time[2] += $secs; for (my $i = 2; $i >= 1; $i--) { if ($time[$i] >= 60) { $time[$i] -= 60; $time[$i-1]++; } } $time[0] -= 24 if $time[0] >= 24; $time = join ':', map { length($_) < 2 ? "0$_" : $_ } @time; print $time;
    Hope this helps...

    gav^