如何只在几天内生成DateTime :: Duration输出?

San*_*ing 11 perl

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

#!/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;
Run Code Online (Sandbox Code Playgroud)

问题是只有输出-22天.

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

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

如何让它在几天内输出结果?

print Dumper $d->delta_days + $d->delta_months*30;
Run Code Online (Sandbox Code Playgroud)

不像一个优雅的解决方案.

Dav*_*aab 25

首先,您需要进行正确的减法.存在delta_md,delta_days,delta_mssubtract_datetime_absolute.根据您以后想要的单位,您需要选择正确的减法.问题是,并非每个单元都可以在没有time_zone信息的情况下进行转换.这就是你需要选择正确的delta方法的原因.

例如,一天可以有23小时或24或25小时,具体取决于时区.因此,您需要指定减法应如何工作.因为你想要几天后,减法需要关注几天,而不是关注几小时.不要使用过载功能,因为它只能做到最合适.

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

my $dur = $date->delta_days($today);
Run Code Online (Sandbox Code Playgroud)

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

如果您不希望这种"最适合",则需要调用该in_units方法并将其仅转换为几天.

my $days = $dur->in_units('days');
Run Code Online (Sandbox Code Playgroud)

但就像我之前说的那样,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');
Run Code Online (Sandbox Code Playgroud)

该程序的输出是:

Weeks:          568
Days:           3
Absolute Days:  3979
Absolute Hours: 95496
Run Code Online (Sandbox Code Playgroud)

仅供参考:
1)您不需要加载DateTime::Duration其加载DateTime.
2)你不需要().这些模块是OOP,不导出/导入任何东西.

  • 它计算两个日期之间的差值.这总是积极的.如果您想要一个负数,您需要检查哪个日期更大,并将结果与​​-1重复. (2认同)