I've run into an odd issue with DateTime and Memoization (often necessary to get decent performance for processing 10-20k records with repeat dates). I've processed a lot of data this way but I recently ran into a few records that caused an infinite loop, below is some simplified sample code that reproduces the behavior. It goes away if I don't memoize DT::from_object, but I still find it odd and thought somebody might be interested in looking into it further (or documenting the potential for trouble?)
I'm using: $DateTime::VERSION = '0.2901'; $DateTime::Set::VERSION = '0.25'; $DateTime::Event::Recurrence::VERSION = '0.16'; with ActiveState under Win32. =cut use Memoize; use DateTime::Format::Strptime; use DateTime::Event::Recurrence; #DateTime::from_object doesn't Memoize well here. #Granted, there maybe ought to be a normalizer for the locale parameter? memoize($_) foreach qw/DateTime::from_object DateTime::new/; my $strp = new DateTime::Format::Strptime(pattern => '%m/%d/%Y %H:%M'); #Behavior seems to be tied to this data, several records preceeding it are OK @F{qw(ETYP TYPE DESCRP SDate EDate M T W R F S U STime ETime ROOM)}= qw(CLSS ACADEMIC 6.27 2/1/2001 2/1/2001 0 0 0 R 0 0 0 900 2300 26-100); $F{Start} =$strp->parse_datetime("$F{SDate} ". substr($F{STime}, 0,-2) .':'. substr($F{STime}, -2, 2)); $F{End} =$strp->parse_datetime("$F{SDate} ". substr($F{ETime}, 0,-2) .':'. substr($F{ETime}, -2, 2)); $hours = DateTime::Set->from_recurrence( start => $F{Start}, before => $F{End}, recurrence => sub { $_[0]->truncate( to => 'hour' ) ->add( hours => 1 ) }, ); $iter = $hours->iterator; #Possibly related: while debugging I somehow, sometimes, managed to get output #below, but the # of hours were off? I'd get back the even hours only... printf "There ought to be %i hours\n", scalar $hours->as_list; #Infinite loop here: #_callback_previous: iterator can't find a previous value, got 2001-02-01 # after 2001-02-01 at DateTime/Set.pm line 338. while ( my $dt = $iter->next ) { my $hour = $dt->hour() || 24; #0..23,24 hours if( $hour >= 7 && $hour <= 24 ){ doMath($F{ROOM}, $F{Start}->dow, 1, $hour, 1); } }; sub doMath{ print "\$stash{ $_[0] }->{usage}->[ $_[1] ]->[ $_[3] ] += $_[2] * $_[4];\n"; $stash{ $_[0] }->{usage}->[ $_[1] ]->[ $_[3] ] += $_[2] * $_[4]; } __END__ -- H4sICNoBwDoAA3NpZwA9jbsNwDAIRHumuC4NklvXTOD0KSJEnwU8fHz4Q8M9i3sGzkS7BBrm OkCTwsycb4S3DloZuMIYeXpLFqw5LaMhXC2ymhreVXNWMw9YGuAYdfmAbwomoPSyFJuFn2x8 Opr8bBBidccAAAA= -- MOTD on Pungenday, the 65th of Discord, in the YOLD 3172: I've lost all sensation in my shirt