下面的脚本以十进制数计算时差,但是我得到一个舍入误差,所以我猜这是因为我最后的转换很糟糕。
问题
有些东西告诉我,表达式可以简化,但是当我有int
,模数和除法时,这个特殊情况下的数学规则是什么?
#!/usr/bin/perl
print f("9:00", "16:45");
sub f {
my $t1 = shift @_;
my $t2 = shift @_;
my $m1 = $1*60+$2 if $t1 =~ m/(\d\d?):(\d\d?)/;
my $m2 = $1*60+$2 if $t2 =~ m/(\d\d?):(\d\d?)/;
my $h = int(($m2-$m1)/60);
return $h + ($h*60+$m2-$m1)%60/60;
}
答案 0 :(得分:6)
自午夜起已经过了几分钟,您已经正确计算了$m1
和$m2
。那么为什么不简单地以小时为单位返回时差:
return ($m2 - $m1) / 60.0;
就“数学规则”而言,也许有助于查看你的return
与我的相比,看看为什么它们是等价的(忽略舍入):
$h + ($h * 60 + $m2 - $m1) % 60 / 60
请注意,($h * 60) % 60
为零,因此该术语基本上会消失,留下:
$h + ($m2 - $m1) % 60 / 60
现在考虑如何计算$h
:它是($m2 - $m1)
除以60的商,删除余数(因为int()
)。另一方面,($m2 - $m1) % 60
恰好是该分区的剩余部分。因此,上面的表达式基本上只是将从$h
中删除的余数部分添加回来。因此它与
($m2 - $m1) / 60
答案 1 :(得分:6)
您可以使用Time::Piece进行简单的日期/时间计算:
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
my $pattern = '%H:%M';
my $start = Time::Piece->strptime('09:00', $pattern);
my $end = Time::Piece->strptime('16:45', $pattern);
my $diff = $end - $start;
print $diff->hours;
7.75
请注意,$diff
实际上是Time::Seconds个对象。
答案 2 :(得分:1)
我会说使用Time::Piece
,但我认为这是某种练习。
在Unix中,所有日期都会转换为自纪元以来的秒数。当一切都在同一单元中时,它可以很容易地对事物进行算术运算。因此,我会将时间转换为分钟,执行操作,然后将时间转换回小时和分钟。这意味着你需要子程序。一个将时间从小时和分钟转换为分钟。一个将分钟转换为小时和分钟。
#! /usr/bin/env perl
#
use warnings;
use strict;
use feature qw(say);
my $time1 = "9:50";
my $time2 = "16:45";
my $time1_in_minutes = convert_to_minutes( $time1 );
my $time2_in_minutes = convert_to_minutes( $time2 );
my $diff_in_minutes = $time2_in_minutes - $time1_in_minutes;
say convert_to_hours( $diff_in_minutes );
sub convert_to_minutes {
my $time = shift;
my ($hours, $minutes) = split /:/, $time;
my $total_minutes = ( $hours * 60 ) + $minutes;
return $total_minutes;
}
sub convert_to_hours {
my $minutes = shift;
my $hours = int $minutes / 60;
$minutes = $minutes % 60;
return sprintf "%d:%02d", $hours, $minutes;
}
通过将工作分解为两个子程序,您可以轻松查看正在发生的事情。另外,你有更多的灵活性。如果我给你时间跑马拉松,我想要平均时间怎么办?您可以使用相同的两个例程。如果我给你每天在工作上花的时间怎么样,我想要总计?同样,您可以使用相同的子例程。
并且,因为更容易看到正在发生的事情,所以更容易纠正编程时出现的错误。更好的是,因为操作干净,我可以开始添加功能。例如,检查我的输入会很好。在我的convert_to_minutes
子例程中,我可能希望确保小时和分钟有效。中间有一个冒号。分钟不超过60分钟。