Computation time on 'contains' for SpanSets

2010-12-01 Thread Per-Olof Jensen
I've been running into the issue of having a SpanSet being incredibly slow
when doing a ->contains on a DateTime->now object.  I've tried spreading the
spanset into an array of spans.  That becomes much faster, but only if there
is no time zone set on those spans.  The moment I put time zones on those
'not unioned' spans I get a massive slowdown in computation time.  This is
going into a large scale project, and I was hoping that this feature would
be able to be used since it does exactly what I need it to do!

Our goal is to take a group of spans and check if the time right now is
within each span (basically a daily schedule across the globe).

Here's a test program illustrating the problem I'm having.  I'm just
wondering if there is any way to make the ->contains faster.


#!/usr/bin/perl

use DateTime::Event::Recurrence;
use DateTime::SpanSet;
use DateTime::Infinite;
use DateTime::Set;
use DateTime;

my ($total_span_set, $start, $end, $spanset);
my @array;
my %tzhash = (
'1' => 'America/Halifax',
'2' => 'America/New_York',
'3' => 'America/Chicago',
'4' => 'America/Denver',
'5' => 'America/Los_Angeles',
'6' => 'America/Nome',
'7' => 'Pacific/Honolulu',
'8' => 'Asia/Tokyo',
);

$x = 7;

while ($x > 0 ){

# Make the set representing the work start times: M-F 9:00 and 13:00
$start = DateTime::Event::Recurrence->weekly
 ( days => $x%6+1, hours => 00 , minutes => 00);
# Make the set representing the work end times: M-F 12:00 and 17:00
$end   = DateTime::Event::Recurrence->weekly
 ( days => $x%6+1, hours => 23, minutes => 59);

# Build a spanset from the set of starting points and ending points
$spanset = DateTime::SpanSet->from_sets
( start_set => $start,
  end_set   => $end );

if ($total_span_set){$total_span_set = $total_span_set->union($spanset)}
else {$total_span_set = $spanset}
push(@array, $spanset);
$x--;
}
# Iterate from Thursday the 3rd to Monday the 6th
my $it = $spanset->iterator
   (start  =>
DateTime->new(year => 2003, month => 1, day => 3),
before =>
DateTime->new(year => 2003, month => 1, day => 7));

while (my $span = $it->next) {
my ($st, $end) = ($span->start(), $span->end());
print $st->day_abbr, " ", $st->hour, " to ", $end->hour, "\n";
}

my $dt = DateTime->new(year => 2003, month => 2, day => 11, hour => 11);


my $timer = DateTime->now;

#Here I'm using the first way.  Using a spanet seems very slow on 'contains'
regardless of having a timezone set or not for the span
my $x = 3;
while( $x ){
$dt->set_time_zone($tzhash{$x%6 + 1});
#Setting a time zone to the SpanSet doesn't seem to affect search time
$total_span_set->set_time_zone($tzhash{2});
if ($total_span_set->contains( $dt )){
print "Found time! \n";
}
}
$result = $timer - DateTime->now;
print "Total time : ".$result->seconds."\n";


#An array of spans, this seems to be very fast without timezones set
$timer = DateTime->now;
$x = 3;
while( $x ){

foreach(@array){
#Setting a time zone to the SpanSet/Spans really hoses search time
$_->set_time_zone($tzhash{2});
if ($_->contains( $dt )){
print "Found time\n";
}
}
$x--;
}

$result = $timer - DateTime->now;
print "Total time : ".$result->seconds."\n";



-- 
Per Jensen
Bolder Thinking - Software Developer


Re: Rounding a DateTime to the nearest minute

2010-12-01 Thread Jaldhar H. Vyas

On Thu, 2 Dec 2010, Rick Measham wrote:


This works in my head:

$dt->add( seconds => 30 )->truncate( to => 'minute' );



Wonderful!  One thing I found out about my data after I wrote is that I 
need to round down if seconds = 30 exactly.  So I just changed your code 
to add 29 seconds and now it works perfectly.


Thanks for your help.


--
Jaldhar H. Vyas 


Re: Rounding a DateTime to the nearest minute

2010-12-01 Thread Rick Measham
This works in my head:

$dt->add( seconds => 30 )->truncate( to => 'minute' );

Cheers!
Rick Measham

On 01/12/2010, at 10:32 PM, "Jaldhar H. Vyas"  wrote:

> Is there a simple way to do this (i.e. 6:14:56 becomes 6:15:00, 6:14:07 
> becomes 6:14::00 etc.) or do I have to roll my own?
> 
> -- 
> Jaldhar H. Vyas 
> -- 
> Message  protected for iSite by MailGuard: e-mail anti-virus, anti-spam and 
> content filtering.http://www.mailguard.com.au
> Click here to report this message as spam:
> https://login.mailguard.com.au/report/1BdnE37tyM/28k4626s5OidVPkt2HIig2/0
> 
-- 
Message  protected for iSite by MailGuard: e-mail anti-virus, anti-spam and 
content filtering.http://www.mailguard.com.au



Rounding a DateTime to the nearest minute

2010-12-01 Thread Jaldhar H. Vyas
Is there a simple way to do this (i.e. 6:14:56 becomes 6:15:00, 6:14:07 
becomes 6:14::00 etc.) or do I have to roll my own?


--
Jaldhar H. Vyas