+ return 1;
+ }
+ return 0;
+}
+
+=item _endpoints TIME CUTOFF_DAY
+
+Given a current time and a day of the month to prorate to, return three
+times: the start of the prorate interval (usually the current time), the
+end of the prorate interval (i.e. the cutoff date), and the time one month
+before the end of the prorate interval.
+
+=cut
+
+sub _endpoints {
+ my $self = shift;
+ my $mnow = shift;
+ my @cutoff_days = sort {$a <=> $b} @_;
+
+ # only works for freq >= 1 month; probably can't be fixed
+ my ($sec, $min, $hour, $mday, $mon, $year) = (localtime($mnow))[0..5];
+ if( $self->option('prorate_round_day',1) ) {
+ # If the time is 12:00-23:59, move to the next day by adding 18
+ # hours to $mnow. Because of DST this can end up from 05:00 to 18:59
+ # but it's always within the next day.
+ $mnow += 64800 if $hour >= 12;
+ # Get the new day, month, and year.
+ ($mday,$mon,$year) = (localtime($mnow))[3..5];
+ # Then set $mnow to midnight on that day.
+ $mnow = timelocal(0,0,0,$mday,$mon,$year);
+ }
+ my $mend;
+ my $mstart;
+ # select the first cutoff day that's on or after the current day
+ my $cutoff_day = min( grep { $_ >= $mday } @cutoff_days );
+ # if today is after the last cutoff, choose the first one
+ $cutoff_day ||= $cutoff_days[0];
+
+ # then, if today is on or after the selected day, set period to
+ # (cutoff day this month) - (cutoff day next month)
+ if ( $mday >= $cutoff_day ) {
+ $mend =
+ timelocal_nocheck(0,0,0,$cutoff_day,$mon == 11 ? 0 : $mon + 1,$year+($mon==11));
+ $mstart =
+ timelocal_nocheck(0,0,0,$cutoff_day,$mon,$year);
+ }
+ # otherwise, set period to (cutoff day last month) - (cutoff day this month)
+ else {
+ $mend =
+ timelocal_nocheck(0,0,0,$cutoff_day,$mon,$year);
+ $mstart =
+ timelocal_nocheck(0,0,0,$cutoff_day,$mon == 0 ? 11 : $mon - 1,$year-($mon==0));