如何使DateTime::工期仅以天为单位输出



此代码查找今天和固定日期之间的差异。

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use DateTime ();
use DateTime::Duration ();
use DateTime::Format::Strptime ();
my $date = "23/05-2022";
my $parser = DateTime::Format::Strptime->new(
    pattern     => '%d/%m-%Y',
    time_zone   => 'local',
    );
$date = $parser->parse_datetime($date);
my $today = DateTime->today(time_zone=>'local');
my $d = DateTime::Duration->new($today - $date);
print Dumper $d->delta_days;

问题是只有22天的产出。

如果我做print Dumper $d;,我也可以看到-130个月。

$VAR1 = bless( {
                 'seconds' => 0,
                 'minutes' => 0,
                 'end_of_month' => 'preserve',
                 'nanoseconds' => 0,
                 'days' => -22,
                 'months' => -130
               }, 'DateTime::Duration' );

如何在几天内输出结果?

进行

print Dumper $d->delta_days + $d->delta_months*30;

接缝不像一个优雅的解决方案。

首先需要做正确的减法。存在delta_mddelta_daysdelta_mssubtract_datetime_absolute。根据您以后需要的单位,您需要选择正确的减法。问题是,不是每个单元都可以在没有时区信息的情况下转换。这就是为什么你需要选择正确的delta方法。

例如,根据时区的不同,一天可以有23小时或24或25小时。因此,您需要指定减法的工作方式。因为你想推迟几天,所以减法需要关注几天,而不是几个小时。不要使用过载功能,因为它只会达到最佳效果。

这意味着你需要做一个delta_days减法。

my $dur = $date->delta_days($today);

现在$dur是一个DateTime::Duration对象。你需要知道,如果可能的话,它总是尽量适合几天、几周、几年、几个月。这意味着你的日子将分为几周和几天。因为这个转换总是一个常数。

如果您不想要这种"最佳匹配",则需要调用in_units方法并将其仅转换为天。

my $days = $dur->in_units('days');

但正如我之前所说,in_units只能在可能的情况下进行转换。使用in_units('hours')的调用对此对象无效,只返回一个零,因为您无法将天转换为小时。例如,如果你想要几个小时,你需要做一个delta_ms,在这个对象上你可以调用in_units('hours')

完整的例子:

#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
use DateTime;
use DateTime::Format::Strptime;
my $date = "23/05-2022";
my $parser = DateTime::Format::Strptime->new(
    pattern     => '%d/%m-%Y',
    time_zone   => 'local',
);
$date = $parser->parse_datetime($date);
my $today = DateTime->new(
    day   => 1,
    month => 7,
    year  => 2011,
    time_zone => 'local'
);  
my $dur = $date->delta_days($today);
say "Weeks:          ", $dur->weeks;
say "Days:           ", $dur->days;
say "Absolute Days:  ", $dur->in_units('days');
say "Absolute Hours: ", $date->delta_ms($today)->in_units('hours');

该程序的输出为:

Weeks:          568
Days:           3
Absolute Days:  3979
Absolute Hours: 95496

仅供参考:
1( 您不需要加载DateTime::Duration,而是加载DateTime
2( 你不需要((。这些模块是面向对象的,不导出/导入任何内容。

通过快速阅读DateTime模块文档,我不相信

DateTime::Duration->new($today - $date)

会做你期望的事。我认为你需要使用

$dur = $today->subtract_datetime($date)

然而,$dur的类型并没有从文档中立即明确。