DateTimeX-Seinfeld

 view release on metacpan or  search on metacpan

lib/DateTimeX/Seinfeld.pm  view on Meta::CPAN

    redo if $skip_this;
    ++$count;
  }

  return $count;
} # end _find_period
#---------------------------------------------------------------------


sub period_containing
{
  my ($self, $date) = @_;

  my $end = $self->start_date->clone;

  $self->_find_period($date, $end);

  $end->subtract_duration( $self->increment );
} # end period_containing

#=====================================================================
# Package Return Value:

__PACKAGE__->meta->make_immutable;
1;

__END__

=head1 NAME

DateTimeX::Seinfeld - Calculate Seinfeld chain length

=head1 VERSION

This document describes version 1.000 of
DateTimeX::Seinfeld, released January 11, 2014.

=head1 SYNOPSIS

  use DateTimeX::Seinfeld;

  my $seinfeld = DateTimeX::Seinfeld->new(
    start_date => $starting_datetime,
    increment  => { weeks => 1 },
  );

  my $chains = $seinfeld->find_chains( \@list_of_datetimes );

  say "Longest chain: $chains->{longest}{length}";
  say "First event in longest chain: $chains->{longest}{start_event}";
  say "The current chain may continue"
    if $chains->{last}{end_period}
       >= $seinfeld->period_containing( DateTime->now );

=head1 DESCRIPTION

DateTimeX::Seinfeld calculates the maximum Seinfeld chain length from
a sorted list of L<DateTime> objects.

The term "Seinfeld chain" comes from advice attributed to comedian
Jerry Seinfeld.  He got a large year-on-one-page calendar and marked a
big red X on every day he wrote something.  The chain of continuous
X's gave him a sense of accomplishment and helped motivate him to
write every day.
(Source: L<http://lifehacker.com/281626/jerry-seinfelds-productivity-secret>)

This module calculates the length of the longest such chain of
consecutive days.  However, it generalizes the concept; instead of
having to do something every day, you can make it every week, or every
month, or any other period that can be defined by a
L<DateTime::Duration>.

Some definitions: B<period> is the time period during which some
B<event> must occur in order to keep the chain from breaking.  More
than one event may occur in a single period, but the period is only
counted once.

=head1 ATTRIBUTES

=head2 start_date

This is the DateTime (or a hashref acceptable to C<< DateTime->new >>)
of the beginning of the first period.  All events passed to
C<find_chains> must be greater than or equal to this value.
(required)


=head2 increment

This is the DateTime::Duration (or a hashref acceptable to
C<< DateTime::Duration->new >>) giving the length of each period.
(required)


=head2 skip

This is a CodeRef that allows you to skip specified periods.  It is
called with one argument, the DateTime at which the period begins.  If
the CodeRef returns a true value, any events taking place during this
period are instead considered to take place in the next period.  (The
CodeRef must not modify the DateTime object it was given.)  (optional)

For example, to skip Sundays:

  skip => sub { shift->day_of_week == 7 }

Using C<skip> does I<not> change the start time of the next period (as
reported by C<period_containing>, C<start_period>, or C<end_period>).
The idea is that events will not normally occur during skipped periods
(or you probably shouldn't be skipping them).  This means that it is
possible for an event to be less than the start time of the period
containing it.

=head1 METHODS

=head2 find_chains

  $info = $seinfeld->find_chains( \@events );
  $info = $seinfeld->find_chains( \@events, $info ); # continue search

This calculates Seinfeld chains from the events in C<@events> (an



( run in 1.461 second using v1.01-cache-2.11-cpan-39bf76dae61 )