每次我试图找到这些日期字符串的差异,都有一个错误。我想知道你是否能帮我这个忙。
my $datecreated = '2021-09-06 04:52:38';
my $dateresolved = '2021-09-06 04:52:48';
my $time_elapsed= $dateresolved - $datecreated;
print $time_elapsed;
我想把结果转换成分钟和小时。
这两个时间戳仅仅是字符串。为了得到这两个时刻之间的持续时间(减去)。我们需要从它们中构建日期时间对象,在一个知道如何找到它们之间的持续时间的库中。一个不错的选择是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对象使得转换成任何特定的期望单位变得更加困难
一般不能在秒、分、日和月之间进行转换,所以这个类永远不会这样做。相反,应该以期望的单位开始创建持续时间,例如,在
DateTime.pm
对象上调用适当的减法/增量方法。
所以上面我使用delta_ms
,因为分钟很容易转换为小时+分钟。秒被丢弃,正如问题所暗示的那样(如果这实际上是无意的,将它们添加到例程中)。
对于更一般的用法,可以使用
use DateTime::Duration;
my $dur = $dt1->subtract_datetime($dt2);
# Easy to extract parts (components) of the duration
say "Hours: ", $dur->hours, " and minutes: ", $dur->minutes; # NOT conversion
core 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
更全面和强大,也有一个生态系统的扩展。
Use Time::Piece自2007年起成为Perl库的标准部分。
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
# Define the format of your inputs
my $format = '%Y-%m-%d %H:%M:%S';
# Convert your date strings into Time::Piece objects
my $datecreated = Time::Piece->strptime('2021-09-06 04:52:38', $format);
my $dateresolved = Time::Piece->strptime('2021-09-06 04:52:48', $format);
# Time::Piece objects can be subtracted from each other.
# This gives the elapsed time in seconds.
my $time_elapsed = $dateresolved - $datecreated;
# Do the calculations to displace the elapsed time in hours,
# minutes and seconds.
printf "%02dh:%02dm:%02dsn",
$time_elapsed->hours,
$time_elapsed->minutes % 60,
$time_elapsed->seconds % 60;