If you already have the periods in Time::Period's format, it should be trivial to write a version of Time::Period's functions which returns DateTime::SpanSets instead of booleans. For example, below are the guts of the wd and hr.
sub wd {
my ($min, $max) = @_
return DateTime::SpanSet->from_set_and_duration(
set => DateTime::Set->from_recurrence(
recurrence => sub {
my ($dt) = @_;
return $dt->truncate(to => 'day')
->add(days => ($min-$dt->wday()+7-1) % 7 + 1);
},
),
days => $max-$min+1,
);
}
sub hr {
my ($min, $max) = @_
return DateTime::SpanSet->from_set_and_duration(
set => DateTime::Set->from_recurrence(
recurrence => sub {
my ($dt) = @_;
$dt = $dt->add(days => 1)
if $dt->hour() >= $min;
return $dt->truncate(to => 'day')->set(hour => $min);
},
),
hours => $max-$min+1,
)
}
# M-F, 9am to 5pm
# wd {mo-fr} hr {9-16}
my $sla_period = wd(1,5)->intersection(hr(9, 16));
Still untested.