Perl DateTime模块计算时间差错误,如何获取正确小时数?
问题
尝试计算2024-01-03T19:00:00与2024-01-07T16:00:00的小时差(正确结果应为93小时),但使用Perl DateTime模块计算时,DateTime::Duration对象的多种方法都只返回21小时,完全忽略了间隔的天数。无论是通过字符串解析还是直接创建DateTime对象,结果都一致。
示例代码1
#!/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;
示例代码2
#!/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
查阅DateTime::Duration相关文档后仍无法得到正确结果,请问如何获取两个日期之间的正确小时数?
解决方案
问题核心是DateTime::Duration会将时间差拆分为天、小时、分钟等独立单位存储,而非直接合并为总小时数。比如你计算的时间差是3天21小时,hours()方法只会返回拆分后的21小时,不会包含天数转换的部分。
以下两种方法可获取正确的总小时数:
方法1:通过时间戳计算差值
将两个DateTime对象转换为UTC时间戳(从epoch开始的秒数),计算差值后除以3600得到总小时数:
my $total_hours = ($sun_date->epoch - $wed_date->epoch) / 3600; say $total_hours; # 输出93
方法2:手动合并天和小时的差值
利用in_units方法同时提取天数和小时数,将天数转换为小时后相加:
my ($days, $hours) = $diff->in_units('days', 'hours'); my $total_hours = $days * 24 + $hours; say $total_hours; # 输出93
补充说明
clock_duration()仅计算当天内的时间差,因此只会返回21小时,不适合跨天场景。delta_days()仅返回天数差,不会自动转换为小时,直接调用in_units('hours')会返回0。
内容的提问来源于stack exchange,提问作者con
相关产品推荐
相关产品推荐

