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;
The problem is that is only outputs -22 days.
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?
Doing
print Dumper $d->delta_days + $d->delta_months*30;
doesn’t seam like an elegant solution.
At first you need to do the correct subtraction. There exists
delta_md,delta_days,delta_msandsubtract_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.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.
That means you need to do a
delta_dayssubtraction.Now $dur is a
DateTime::Durationobject. 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.If you don’t want this “best fit” you need to call the
in_unitsmethod and convert it only to days.But like i said before
in_unitsonly can do a conversion where it is possible. A call within_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 adelta_ms, and on this object you can callin_units('hours')The complete example:
The output of this program is:
And just for info:
1) You don’t need to load
DateTime::Durationits get loaded withDateTime.2) You dont need (). These modules are OOP and don’t export/import anything.