问题描述
此代码找出今天和固定日期之间的差异.
This code finds the difference between today and a fixed date.
#!/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 天.
The problem is that is only outputs -22 days.
如果我执行 print Dumper $d;
我也可以看到 -130 个月.
If I do print Dumper $d;
I can see the -130 months as well.
$VAR1 = bless( {
'seconds' => 0,
'minutes' => 0,
'end_of_month' => 'preserve',
'nanoseconds' => 0,
'days' => -22,
'months' => -130
}, 'DateTime::Duration' );
如何让它在几天内输出结果?
How do I get it to output the result in days?
做
print Dumper $d->delta_days + $d->delta_months*30;
看起来不像一个优雅的解决方案.
doesn't seam like an elegant solution.
推荐答案
首先你需要做正确的减法.存在 delta_md
、delta_days
、delta_ms
和 subtract_datetime_absolute
.根据您以后想要的单位,您需要选择正确的减法.问题是不是每个单位都可以在没有 time_zone 信息的情况下转换.这就是为什么您需要选择正确的增量方法的原因.
At first you need to do the correct subtraction. There exists delta_md
, delta_days
, delta_ms
and subtract_datetime_absolute
. Depending on which unit you later want, you need to pick the right subtraction. The problem is that not every unit is convertible later without time_zone information. Thats the reason why you need to pick the correct delta method.
例如,一天可以有 23 小时或 24 小时或 25 小时,具体取决于时区.因此,您需要指定减法应该如何工作.因为你想要几天后,减法需要关注天,而不是关注小时.不要使用重载功能,因为它只会最适合.
For example a day can have 23 Hours or 24 or 25 Hours, depending on the time zone. Because of that, you need to specify how the subtraction should work. Because you want the days later, the subtraction need to focus on days, rather focus on hours. Don't use the overload feature, because it only does a best fit.
这意味着你需要做一个 delta_days
减法.
That means you need to do a delta_days
subtraction.
my $dur = $date->delta_days($today);
现在 $dur 是一个 DateTime::Duration
对象.您需要知道,如果可能的话,它总是试图最适合几天、几周、几年、几个月.这意味着您的日子将分成数周和数天.因为这种转换总是一个常数.
Now $dur is a DateTime::Duration
object. You need to knew that it always tries to best fit the days, weeks, years, months if possible. That means your days will split in weeks and days. Because this conversion is always a constant.
如果您不想要这种最佳匹配",则需要调用 in_units
方法并将其转换为天数.
If you don't want this "best fit" you need to call the in_units
method and convert it only to days.
my $days = $dur->in_units('days');
但就像我之前说的 in_units
只能在可能的情况下进行转换.使用 in_units('hours')
调用将不会在此对象上工作,只会返回零,因为您无法将天转换为小时.例如,如果你想要小时,你需要做一个 delta_ms
,并且在这个对象上你可以调用 in_units('hours')
But like i said before in_units
only can do a conversion where it is possible. A call with in_units('hours')
will not work on this object and just return a zero because you cant convert days to hours. If you want hours for example, you need to do a delta_ms
, and on this object you can call 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)你不需要().这些模块是面向对象的,不导出/导入任何内容.
And just for info:
1) You don't need to load DateTime::Duration
its get loaded with DateTime
.
2) You dont need (). These modules are OOP and don't export/import anything.
这篇关于如何仅以天为单位制作 DateTime::Duration 输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,WP2