如何在perl中减去日期并将其转换为分钟和小时?



每次我试图找到这些日期字符串的差异,都有一个错误。我想知道你是否能帮我这个忙。

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;

相关内容

  • 没有找到相关文章

最新更新