这两个时间戳只是字符串。为了及时获得这两个时刻之间的持续时间(“减去”它们),需要在一个知道如何找到它们之间的持续时间的库中从它们构建日期时间对象。一个不错的选择是DateTime
use warnings;
use strict;
use feature 'say';
use DateTime;
use DateTime::Format::Strptime;
my ($ts1, $ts2) = (@ARGV == 2)
? @ARGV : ('2021-09-05 04:52:38', '2021-09-01 04:52:48');
my $strp = DateTime::Format::Strptime->new(
pattern => '%F %T', time_zone => 'floating', on_error => 'croak'
);
my ($dt1, $dt2) = map { $strp->parse_datetime($_) } $ts1, $ts2;
# Get difference in hours and minutes (seconds discarded per question)
my ($hrs, $min) = delta_hm($dt1, $dt2);
say "$hrs hours and $min minutes";
# Or (time-stamp hh:mm in scalar context)
my $ts_hm = delta_hm($dt1, $dt2);
say $ts_hm;
# To get wanted units (hours+minutes here) best use a delta_X
sub delta_hm {
my ($dt1, $dt2) = @_;
my ($min, $sec) = $dt1->delta_ms($dt2)->in_units('minutes', 'seconds');
my $hrs = int( $min / 60 );
$min = $min % ($hrs*60) if $hrs;
return (wantarray) # discard seconds
? ($hrs, $min)
: join ':', map { sprintf "%02d", $_ } $hrs, $min;
}
这里的硬编码输入时间戳与问题中的不同;那些会使一小时+分钟的差异为零,因为它们仅以秒为单位! (这是有意的吗?)还可以提交两个时间戳字符串作为该程序的输入。
请注意,通用 duration object 使得转换为任何特定的所需单位变得更加困难
通常不能在秒、分钟、天和月之间转换,所以这个类永远不会这样做。相反,使用所需的单位来创建持续时间,例如通过在 DateTime.pm 对象上调用适当的减法/增量方法。
所以上面我使用delta_ms,因为分钟很容易转换为小时+分钟。正如问题所暗示的那样,秒数被丢弃(如果这实际上是无意的,则将它们添加到例程中)。
但是对于更一般的用途,我们可以做到
use DateTime::Duration;
my $dur = $dt1->subtract_datetime($dt2);
# Easy to extract parts of the duration, like
say "Hours: ", $dur->hours, " and minutes: ", $dur->minutes; # NOT conversion
# This leaves out possible longer units (days, months, years)
核心Time::Piece 也可以做到这一点
use warnings;
use strict;
use feature 'say';
use Time::Piece;
my ($ts1, $ts2) = (@ARGV)
? @ARGV : ('2021-09-05 04:52:38', '2021-09-01 04:52:48');
my ($dt1, $dt2) = map { Time::Piece->strptime($_, "%Y-%m-%d %T") } $ts1, $ts2;
# In older module versions the format specifier `%F` (`%Y-%m-%d`) may fail
# so I spell it out here; the %T (for %H:%M:%S) should always be good
# For local times (not UTC) better use Time::Piece::localtime->strptime
my $delta = $dt1 - $dt2;
# say $delta->pretty;
my $hrs = int( $delta->hours );
my $min = int($delta->minutes) - ($hrs//=0)*60;
say "$hrs:$min";
这要简单得多,但要注意Time::Piece 的偶尔棘手的(导致错误的)API。
请注意,虽然Time::Piece 是核心、简洁且轻量级(并且正确!),但DateTime 更加全面和强大,还具有扩展生态系统。