I've attached a patch for current() and set_time_zone(). There are no tests.
2008/12/19 Elliot Shank <p...@galumph.com>: > 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;