How to make DateTime::Duration output only in days?

前端 未结 2 1734
迷失自我
迷失自我 2020-12-06 17:14

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::D         


        
相关标签:
2条回答
  • 2020-12-06 17:52

    From a quick read of the DateTime module doc, I don't believe that

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

    will do what you expect. I believe you need to use

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

    The type of $dur is not immediately clear from the docs, however.

    0 讨论(0)
  • 2020-12-06 18:04

    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.

    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_days subtraction.

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

    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.

    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');
    

    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')

    The complete example:

    #!/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');
    

    The output of this program is:

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

    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.

    0 讨论(0)
提交回复
热议问题