Produces nicely formated time from elapsed seconds.
This is kind of like Formatting elapsed time, but has more options and has date units from seconds into years.
sub dhm { my $time = shift; my (@times, @time); my @format = qw(m h d); push @times, ($time / 60) % 60; # Minutes push @times, ($time / (60 * 60)) % 24; # Hours push @times, int($time / (24 * 60 * 60)); # Days for my $i (0 .. $#times) { push @time, "$times[$i]\cB$format[$i]\cB" if $times[$i] > 0; } return join ' ', reverse @time; } sub time2string { my %defaults = ( long_format => 1, spacing => 1, bold => 0 ); my $time = shift; my %args = (%defaults, @_); my @format; if ($args{format}) { $args{long_format} = 1; @format = split ' ', $args{format}; } if (@format) { die "error: format needs excatly 7 values.\n" unless $#format == 6 +; } else { if ($args{long_format} == 1) { @format = qw(sec min hour day week month year); } elsif ($args{long_format} == 2) { @format = qw(second minute hour day week month year); } elsif (!$args{format} && !$args{long_format}) { @format = qw(s m h d w mo y); } } die "error: time must only only be digits.\n" if !defined $time || + $time !~ /^\-?\d+$/; my $prefix = ''; if ($time < 0) { $time = - $time; $prefix = "- "; } my (@times, @data); push @times, $time % 60; # Seconds push @times, ($time / 60) % 60; # Minutes push @times, ($time / (60 * 60)) % 24; # Hours push @times, int($time / (24 * 60 * 60)); # Days my $modulo = sub { my ($days, $d) = @_; my $return; if ($d >= $days) { $return = int($d / $days); $d = $d % $days; } else { $return = 0; } return $return, $d; }; ($times[6], $times[3]) = $modulo->(365, $times[3]); # Years ($times[5], $times[3]) = $modulo->(30, $times[3]); # Months ($times[4], $times[3]) = $modulo->(7, $times[3]); # Weeks $time = defined $prefix ? $prefix : undef; for my $i (reverse 0 .. $#times) { next if $times[$i] == 0; $format[$i] .= $times[$i] > 1 && $args{long_format} && !$args{ +format} ? 's ' : ' '; $time .= $args{spacing} ? "$times[$i] $format[$i]" : "$t +imes[$i]$format[$i]"; } $time =~ s#([A-Z]+)#\cB$1\cB#ig if $args{bold} == 1; return $time; }
example usage:
time2string(time, bold => 1) # Bold text for IRC.
9y 4mo 1w 2d 8h 13m 11s
time2string(time, long_format => 1) # Use long(er) unit names.
9 years 4 months 1 week 2 days 8 hours 13 mins 11 secs
time2string(time, long_format => 2) # Full length unit names.
9 years 4 months 1 week 2 days 8 hours 13 minutes 11 seconds
time2string(time, format => 'Sec Min Hour Day Week Month Year'); # De +fine your own unit names.
9 Year 4 Month 1 Week 2 Day 8 Hour 13 Min 11 Sec
time2string(time, spacing => 0, format => 'Sec Min Hour Day Week Mon +th Year'); # Turn off spacing.
9Year 4Month 1Week 2Day 8Hour 13Min 11Sec
dhm(time) # For things that don't need a lot of spiff.
391d 17h 49m