问题
Is there a CPAN module that can convert a number of seconds to a human-readable English description of the interval?
secToEng( 125 ); # => 2 min 5 sec
secToEng( 129_600 ); # => 1 day 12 h
The format isn't important as long as it's human-readable.
I know that it would be trivial to implement.
回答1:
Since Perl v5.9.5, the modules Time::Seconds and Time::Piece are part of the core Perl distribution. So you can use them without installing additional modules.
perl -MTime::Seconds -e 'my $s=125; my $ts=new Time::Seconds $s; print $ts->pretty, "\n"'
# 2 minutes, 5 seconds
perl -MTime::Seconds -e 'my $s=129_600; my $ts=Time::Seconds->new($s); print $ts->pretty, "\n"'
# 1 days, 12 hours, 0 minutes, 0 seconds
You can also use stuff like $ts->weeks
, $ts->minutes
, etc.
回答2:
It turns out that Time::Duration does exactly this.
$ perl -MTime::Duration -E 'say duration(125)'
2 minutes and 5 seconds
$ perl -MTime::Duration -E 'say duration(129_700)'
1 day and 12 hours
From the synopsis:
Time::Duration - rounded or exact English expression of durations
Example use in a program that ends by noting its runtime:
my $start_time = time(); use Time::Duration; # then things that take all that time, and then ends: print "Runtime ", duration(time() - $start_time), ".\n";
Example use in a program that reports age of a file:
use Time::Duration; my $file = 'that_file'; my $age = $^T - (stat($file))[9]; # 9 = modtime print "$file was modified ", ago($age);
回答3:
DateTime can be used:
#!/usr/bin/env perl
use strict;
use warnings;
use DateTime;
use Lingua::EN::Inflect qw( PL_N );
my $dt = DateTime->from_epoch( 'epoch' => 0 );
$dt = $dt->add( 'seconds' => 129_600 );
$dt = $dt - DateTime->from_epoch( 'epoch' => 0 );
my @date;
push @date, $dt->days . PL_N( ' day', $dt->days ) if $dt->days;
push @date, $dt->hours . PL_N( ' hour', $dt->hours ) if $dt->hours;
push @date, $dt->minutes . PL_N( ' minute', $dt->minutes ) if $dt->minutes;
push @date, $dt->seconds . PL_N( ' second', $dt->seconds ) if $dt->seconds;
print join ' ', @date;
Output
1 day 12 hours
回答4:
The DateTime modules are what you want.
DateTime::Duration and DateTime::Format::Duration will do what you need.
回答5:
I wasn't able to find such code a while back, so I wrote these two routines. The second sub uses the first and does what you are looking for.
#-----------------------------------------------------------
# format_seconds($seconds)
# Converts seconds into days, hours, minutes, seconds
# Returns an array in list context, else a string.
#-----------------------------------------------------------
sub format_seconds {
my $tsecs = shift;
use integer;
my $secs = $tsecs % 60;
my $tmins = $tsecs / 60;
my $mins = $tmins % 60;
my $thrs = $tmins / 60;
my $hrs = $thrs % 24;
my $days = $thrs / 24;
if (wantarray) {
return ($days, $hrs, $mins, $secs);
}
my $age = "";
$age .= $days . "d " if $days || $age;
$age .= $hrs . "h " if $hrs || $age;
$age .= $mins . "m " if $mins || $age;
$age .= $secs . "s " if $secs || $age;
$age =~ s/ $//;
return $age;
}
#-----------------------------------------------------------
# format_delta_min ($seconds)
# Converts seconds into days, hours, minutes, seconds
# to the two most significant time units.
#-----------------------------------------------------------
sub format_delta_min {
my $tsecs = shift;
my ($days, $hrs, $mins, $secs) = format_seconds $tsecs;
# show days and hours, or hours and minutes,
# or minutes and seconds or just seconds
my $age = "";
if ($days) {
$age = $days . "d " . $hrs . "h";
}
elsif ($hrs) {
$age = $hrs . "h " . $mins . "m";
}
elsif ($mins) {
$age = $mins . "m " . $secs . "s";
}
elsif ($secs) {
$age = $secs . "s";
}
return $age;
}
来源:https://stackoverflow.com/questions/7545664/is-there-a-cpan-module-for-converting-seconds-to-english