假设以下 DateTime::SpanSet
包含 6 个 DateTime::Span
对象(打印的 start
和 end
DateTime
每个跨度),我想反转它并用一个跨度限制它。
[2013-02-04T00:00:00 -> 2013-02-04T03:00:00]
[2013-02-04T07:30:00 -> 2013-02-04T12:00:00]
[2013-02-04T12:45:00 -> 2013-02-04T16:45:00]
[2013-02-05T07:30:00 -> 2013-02-05T16:45:00]
[2013-02-06T08:00:00 -> 2013-02-06T16:30:00]
[2013-02-07T16:00:00 -> 2013-02-08T16:30:00]
使用 complement
反转它,给出以下内容:
[-inf -> 2013-02-04T00:00:00]
[2013-02-04T03:00:00 -> 2013-02-04T07:30:00]
[2013-02-04T12:00:00 -> 2013-02-04T12:45:00]
[2013-02-04T16:45:00 -> 2013-02-05T07:30:00]
[2013-02-05T16:45:00 -> 2013-02-06T08:00:00]
[2013-02-06T16:30:00 -> 2013-02-07T16:00:00]
[2013-02-08T16:30:00 -> inf]
我正在寻找的最终结果应受 2013-02-04T00:00:00 -> 2013-02-11T00:00 的
,得到以下结果:DateTime::Span
限制: 00
[2013-02-04T03:00:00 -> 2013-02-04T07:30:00]
[2013-02-04T12:00:00 -> 2013-02-04T12:45:00]
[2013-02-04T16:45:00 -> 2013-02-05T07:30:00]
[2013-02-05T16:45:00 -> 2013-02-06T08:00:00]
[2013-02-06T16:30:00 -> 2013-02-07T16:00:00]
[2013-02-08T16:30:00 -> 2013-02-11T00:00:00]
我可以通过以下方式实现这一点:
sub invertSpansetByBoundary {
my $spanset = shift;
my $boundary = shift;
$spanset = $spanset->complement;
my $iter = $spanset->iterator(span => $boundary);
my $ss = DateTime::SpanSet->empty_set();
while(my $timespan = $iter->next) {
$ss = $ss->union($timespan);
}
return $ss;
}
有没有可能以更好的方式做到这一点?
最佳答案
这个问题的解决方案似乎太容易了,我实际上构建了一个测试工具来根据我的结果验证您的结果,我在下面包含了这些结果。我的 Perl 有点生疏,但这是我想出的解决方案:
sub alternateInvert {
my $spanset = shift;
my $boundary = shift;
return $boundary->complement($spanset);
}
使用它给我的结果与您的函数相同。 这是测试工具:
#!/opt/local/bin/perl
use DateTime::Span;
use DateTime::Format::RFC3339;
use DateTime;
use strict;
use warnings;
sub invertSpansetByBoundary {
my $spanset = shift;
my $boundary = shift;
$spanset = $spanset->complement;
my $iter = $spanset->iterator(span => $boundary);
my $ss = DateTime::SpanSet->empty_set();
while(my $timespan = $iter->next) {
$ss = $ss->union($timespan);
}
return $ss;
}
sub alternateInvert {
my $spanset = shift;
my $boundary = shift;
return $boundary->complement($spanset);
}
sub printSpanset {
my $spanset = shift;
my $iter = $spanset->iterator(span => $spanset);
while(my $timespan = $iter->next) {
printf "[%s -> %s]\n", $timespan->start, $timespan->end;
}
}
my $datestrs = [
["2013-02-04T00:00:00Z", "2013-02-04T03:00:00Z"],
["2013-02-04T07:30:00Z", "2013-02-04T12:00:00Z"],
["2013-02-04T12:45:00Z", "2013-02-04T16:45:00Z"],
["2013-02-05T07:30:00Z", "2013-02-05T16:45:00Z"],
["2013-02-06T08:00:00Z", "2013-02-06T16:30:00Z"],
["2013-02-07T16:00:00Z", "2013-02-08T16:30:00Z"]];
my $spanset = DateTime::SpanSet->empty_set();
my $format = DateTime::Format::RFC3339->new();
foreach my $set (@$datestrs) {
my $startdt = $format->parse_datetime($set->[0]);
my $enddt = $format->parse_datetime($set->[1]);
$spanset = $spanset->union(DateTime::Span->from_datetimes(start => $startdt, end => $enddt));
}
my $bstartdt = $format->parse_datetime("2013-02-04T00:00:00Z");
my $benddt = $format->parse_datetime("2013-02-11T00:00:00Z");
my $boundary = DateTime::Span->from_datetimes(start => $bstartdt, end => $benddt);
my $result;
print "Input:\n";
printSpanset($spanset);
# $result = invertSpansetByBoundary($spanset, $boundary);
# print "\nBaseline Result:\n";
# printSpanset($result);
$result = alternateInvert($spanset, $boundary);
print "\nImproved Result:\n";
printSpanset($result);
关于perl - 在 perl 中限制倒置 DateTime::SpanSet 的更好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19377074/