3

次のDateTime::SpanSet6 つDateTime::Spanのオブジェクト (印刷されたものstartend 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]

私が探している最終結果はDateTime::Spanfromによって制限され2013-02-04T00:00:00 -> 2013-02-11T00: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 -> 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;
}

これをより良い方法で行うことは可能ですか?

4

1 に答える 1

0

これに対する解決策は簡単すぎるように思われましたが、実際にテスト ハーネスを構築して、自分の結果と照らし合わせて結果を検証しました。これを以下に示します。私の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);
于 2013-10-25T21:22:02.540 に答える