DateTime.pm代码,用于确定日期之间的天数

时间:2016-05-09 18:45:48

标签: perl datetime

我有一个函数我尝试使用Perl中的DateTime模块重新创建:

$x=dates_difference($year,$month,$day,$cyear,$curmon,$cmday)

给出两个日期,当前日期/时间格式为:$ cyear,$ cmon,$ cmday(年份,月份编号,月份日期编号)和另一个早期格式相同的日期:$ year ,$ month,$ day,我想返回两个日期之间的天数。我不需要它是100%精确的,只要它是+/-一两天所以时间和时区并不重要。

我一直在阅读各种例子,并且找不到任何明确的内容。

我试过了:

$x = $dtcurrent->subtract_datetime_absolute($dt1);

并收到错误DateTime::Duration does not overload comparison. See the documentation on the compare() method for details.

示例:

$x = $dtcurrent->delta_days($dt1);
if ($x > 30) ...

它似乎没有返回我可以在数字比较中使用的数字。

4 个答案:

答案 0 :(得分:1)

您想使用delta_days

sub dates_difference {
   my ($year1, $month1, $day2, $year2, $mon2, $day2) = @_;
   my $dt1 = DateTime->new( year => $year1, month => $month1, day => $day1, time_zone => 'floating' );
   my $dt2 = DateTime->new( year => $year2, month => $month2, day => $day2, time_zone => 'floating' );
   return $dt2->delta_days($dt1)->in_units('days');
}

以下效率更高:

sub dates_difference {
   my ($year1, $month1, $day2, $year2, $mon2, $day2) = @_;
   my $dt1 = DateTime->new( year => $year1, month => $month1, day => $day1, time_zone => 'floating' );
   my $dt2 = DateTime->new( year => $year2, month => $month2, day => $day2, time_zone => 'floating' );
   return abs( ( $dt2->local_rd_values )[0] - ( $dt1->local_rd_values )[0] );
}

如果您希望对差异进行签名,请使用以下命令:

sub dates_difference {
   my ($year1, $month1, $day2, $year2, $mon2, $day2) = @_;
   my $dt1 = DateTime->new( year => $year1, month => $month1, day => $day1, time_zone => 'floating' );
   my $dt2 = DateTime->new( year => $year2, month => $month2, day => $day2, time_zone => 'floating' );
   return ( $dt2->local_rd_values )[0] - ( $dt1->local_rd_values )[0];
}

答案 1 :(得分:1)

使用核心Time::Piece模块。它比DateTime重量轻得多,并且做了所有必要的事情

以下是您的一些示例代码

use strict;
use warnings 'all';
use feature 'say';

use Time::Piece ();

my $x = dates_difference(2017, 1, 1, 2016, 5, 9);

say "$x days until the New Year";


sub dates_difference {
    my ($y, $m, $d, $cy, $cm, $cd) = @_;
    my $date  = Time::Piece->strptime("$y $m $d", '%Y %m %d');
    my $cdate = Time::Piece->strptime("$cy $cm $cd", '%Y %m %d');
    ($date - $cdate)->days;
}

输出

237 days until the New Year

答案 2 :(得分:0)

将代码行组装成示例:

my $dtcurrent = DateTime->new(
    year  => 2016,
    month => 5,
    day   => 9,
);
my $old = DateTime->new(
    year  => 2016,
    month => 1,
    day   => 1,
);

(我使用固定的$dtcurrent来更简单地解释计算结果。生产中应该$dtcurrent = DateTime->now。)

my $distance = $old->delta_days($dtcurrent);

$distanceDateTime::Duration对象,具有不同的属性:

print $distance->years;
0

毫不奇怪:2016年 - > 2016年是0年的差异。

print $distance->months;
0

print $distance->days;
3

发生什么事了? DateTime手册说:

  

“delta_days()”方法返回仅包含天数的持续时间。

不是你的预期。但请尝试->in_units

print $distance->in_units('days');
129

替代:日期::计算

对于此用例,我更喜欢Date::Calc

use Date::Calc qw(Delta_Days Today);
print Delta_Days(Today(), 2016, 1, 1);
-129

交换Today()和日期以获得正数。 Today()也可能被另一个$year, $month, $day替换。

替代:时间戳

use Time::Local qw( timegm ); # Core module

my ($year_now, $month_now, $day_now) = ( localtime(time) )[5,4,3];

my $ts     = timegm($year,     $month,     $day,     0, 0, 0);
my $ts_now = timegm($year_now, $month_now, $day_now, 0, 0, 0);

my $days = int(abs(($ts_now - $ts)) / (24*60*60));

timegmgmtime相反:将日期部分转换为时间戳。由于所有gmtime天都有24 * 60 * 60秒,我们可以通过以gmt查找这些日期的时间戳,计算差异,然后除以24 * 60 * 60来查找两个日期之间的天数。这显然非常复杂且容易出错。

答案 3 :(得分:0)

在这里,我提出的似乎有用......

use DateTime;

my $dt_now = DateTime->now( time_zone => 'local' )->set_time_zone('floating');

my $dt1 = DateTime->new(
   year      => $year,
   month     => $month,
   day       => $day,
   time_zone => 'floating',
);

my $days = $dt_now->delta_days($dt1)->in_units('days');