Inspirado em https://perlmaven.com/datetime , estou tentando encontrar o número de horas de diferença entre 2024-01-03T19:00:00 e 2024-01-07T16:00:00 (93 horas).
#!/usr/bin/env perl
use 5.038;
use warnings FATAL => 'all';
use autodie ':default';
use DDP;
use Devel::Confess 'color';
use DateTime;
sub str_to_date ($date) {
if ($date =~ m/^(\d+) # year
\-(\d{1,2}) # month
\-(\d{1,2}) # day
T
(\d+) # hour
:
(\d+) # minutes
:
(\d+) # seconds
/x) {
return DateTime -> new(
year => $1,
month => $2,
day => $3,
hour => $4,
minute=> $5,
second=> $6,
);
} else {
die "$date failed regex.";
}
} # later dates are "greater"
my $wed_date = str_to_date('2024-01-03T19:00:00');
say $wed_date->day;
my $sun_date = str_to_date('2024-01-07T16:00:00');
my $diff = $sun_date - $wed_date; # returns a duration object
p $diff;
say $diff->clock_duration->in_units('hours'); # 21, but should be 93
say $diff->in_units('hours'); # 21 again
say $diff->hours; # 21 again
say $sun_date->delta_days($wed_date)->in_units('hours'); # 0
p $diff->deltas;
todos os métodos que encontrei em https://metacpan.org/pod/DateTime::Format::Duration estão fornecendo respostas incorretas.
Alternativamente, se eu remover a análise,
#!/usr/bin/env perl
use 5.038;
use warnings FATAL => 'all';
use autodie ':default';
use DDP;
use Devel::Confess 'color';
use DateTime;
my $wed_date = DateTime->new(
year => 2024,
month=>1,
day=>3,
hour=>19
);#str_to_date('2024-01-03T19:00:00');
my $sun_date = DateTime->new(
year=>2024,
month=>1,
day=>7,
hour=>16#my $sun_date = str_to_date('2024-01-07T16:00:00');
);#
say $wed_date->day;
my $diff = $sun_date - $wed_date;
p $diff;
say $diff->clock_duration->in_units('hours'); # 21, but should be 93
say $diff->in_units('hours'); # 21 again
say $diff->hours; # 21 again
say $sun_date->delta_days($wed_date)->in_units('hours'); # 0
p $diff->deltas; # 10
as respostas são idênticas.
o objeto DateTime::Duration parece estar ignorando os dias intermediários e focando apenas na diferença entre as horas.
Como posso obter o número correto de horas entre duas datas?
a resposta, de acordo com https://metacpan.org/pod/DateTime#How-DateTime-Math-Works
que é um objeto DateTime::Duration:
o número de segundos, 334.800, é igual a 93 horas, a resposta correta.
Obrigado aos comentaristas.
Use
->delta_ms
em vez de->subtract_datetime
(o método invocado pela subtração).Uma duração medida em dias não pode ser convertida em horas, pois nem todos os dias têm o mesmo número de horas. Na verdade, apenas estas conversões são seguras:
Como tal,
->in_units( 'hours' )
converte apenas os componentes de hora e minuto da duração em horas.$sun_date - $wed_date
retorna uma duração de 3 dias e 1260 minutos.->in_units( 'hours' )
retorna int( 0 + 1260/60 ) = 21 horas.A solução é criar uma duração que consista em horas e/ou minutos em vez de dias.
$sun_date->delta_ms( $wed_date )
retorna uma duração de 5.580 minutos.->in_units( 'hours' )
retorna int( 0 + 5580/60 ) = 93 horas.