I've attached a patch for current() and set_time_zone().
There are no tests.
2008/12/19 Elliot Shank <[email protected]>:
> I now have a case where I'm trying to set up a set of weekly recurrences
> that cover the entire week: if I've got Tuesday at 5pm and Thursday at
> 11:30am, there are two SpanSets, on the covers the Tuesday to Thursday range
> and one that covers the Thursday to Tuesday range. I'm running into
> problems with the degenerate case where there's only one point for the week.
> If I don't set the time zone on the SpanSet, I get what I'm expecting, with
> one exception that I can work around. However, if I touch the time zone,
> then things go awry, even if I use the intermediary floating time zone
> trick.
>
> If I don't set the time zone, I get correct results, except for precisely at
> the time of the single anchor, but in that case, only the end is wrong, and
> I can easily work around that.
>
> If I do set the time zone, pulling the currently effective span from the set
> results in spans that are infinite in both directions.
>
>
> With no time zone changes, now start: 2008-12-15T08:30:00 end:
> 2008-12-22T08:30:00
> With no time zone changes, 6:30 start: 2008-12-08T08:30:00 end:
> 2008-12-15T08:30:00
> With no time zone changes, 7:30 start: 2008-12-08T08:30:00 end:
> 2008-12-15T08:30:00
> With no time zone changes, 8:30 start: 2008-12-15T08:30:00 end:
> inf
> With no time zone changes, 9:30 start: 2008-12-15T08:30:00 end:
> 2008-12-22T08:30:00
> With no time zone changes, 10:30 start: 2008-12-15T08:30:00 end:
> 2008-12-22T08:30:00
> With no time zone changes, 11:30 start: 2008-12-15T08:30:00 end:
> 2008-12-22T08:30:00
> With time zone specified, now start: -inf end: inf
> With time zone specified, 6:30 start: -inf end: inf
> With time zone specified, 7:30 start: -inf end: inf
> With time zone specified, 8:30 start: -inf end: inf
> With time zone specified, 9:30 start: -inf end: inf
> With time zone specified, 10:30 start: -inf end: inf
> With time zone specified, 11:30 start: -inf end: inf
> With intermediary floating time zone, now start: -inf end: inf
> With intermediary floating time zone, 6:30 start: -inf end: inf
> With intermediary floating time zone, 7:30 start: -inf end: inf
> With intermediary floating time zone, 8:30 start: -inf end: inf
> With intermediary floating time zone, 9:30 start: -inf end: inf
> With intermediary floating time zone, 10:30 start: -inf end: inf
> With intermediary floating time zone, 11:30 start: -inf end: inf
>
>
> -----
>
> use DateTime;
> use DateTime::Event::Recurrence;
> use DateTime::SpanSet;
>
>
> my $recurrence =
> DateTime::Event::Recurrence->weekly(
> days => 1, hours => 8, minutes => 30,
> );
>
> my $base_span_set =
> DateTime::SpanSet
> ->from_sets(start_set => $recurrence, end_set => $recurrence);
>
> dump_end_points(
> $base_span_set,
> 'With no time zone changes',
> );
> dump_end_points(
> $base_span_set
> ->clone()
> ->set_time_zone('America/Chicago'),
> 'With time zone specified',
> );
> dump_end_points(
> $base_span_set
> ->clone()
> ->set_time_zone('floating')
> ->set_time_zone('America/Chicago'),
> 'With intermediary floating time zone',
> );
>
> sub dump_end_points {
> my ($span_set, $name) = @_;
>
> my $format = "%36s, %5s start: %s end: %s\n";
>
> my $span = $span_set->current( DateTime->now() )->span();
> printf $format, $name, 'now', $span->start(), $span->end();
>
> foreach my $hour (6..11) {
> $span =
> $span_set
> ->current(
> DateTime->new(
> year => 2008,
> month => 12,
> day => 15,
> hour => $hour,
> minute => 30,
> )
> )
> ->span();
> printf $format, $name, "$hour:30", $span->start(), $span->end();
> }
> }
>
--- /Users/flavioglock/projects/datetime/perl-date-time/modules/DateTime-Set/trunk/lib/DateTime/SpanSet.pm 2008-06-21 09:37:43.000000000 +0200
+++ lib/DateTime/SpanSet.pm 2008-12-19 23:06:33.000000000 +0100
@@ -85,12 +85,12 @@
if ( ref($min) )
{
$min = $min->clone;
- $min->set_time_zone( $tz );
+ $min->set_time_zone( 'floating' );
}
if ( ref($max) )
{
$max = $max->clone;
- $max->set_time_zone( $tz );
+ $max->set_time_zone( 'floating' );
}
return Set::Infinite::_recurrence->new( $min, $max );
},
@@ -292,10 +292,30 @@
sub current {
my $self = shift;
- my $return = $self->intersected_spans( $_[0] );
+ my $previous;
+ my $next;
+ {
+ my $min;
+ $min = $_[0]->min if UNIVERSAL::can( $_[0], 'union' );
+ $min = $_[0] if ! defined $min;
+ return undef if ! ref( $min ) && $min == INFINITY;
+ my $span = DateTime::Span->from_datetimes( end => $min );
+ my $iterator = $self->intersection( $span );
+ $previous = $iterator->previous;
+ $span = DateTime::Span->from_datetimes( start => $min );
+ $iterator = $self->intersection( $span );
+ $next = $iterator->next;
+ }
+ return $previous unless defined $next;
+
+ my $dt1 = defined $previous
+ ? $next->union( $previous )
+ : $next;
+
+ my $return = $dt1->intersected_spans( $_[0] );
- $return = $self->previous( $_[0] )
- if ( ! defined $return->max );
+ $return = $previous
+ if !defined $return->max;
bless $return, 'DateTime::SpanSet'
if defined $return;