From 9341b3eb6b1cfa2063666199e42d05ccc40fd573 Mon Sep 17 00:00:00 2001 From: Marcel de Rooy Date: Tue, 30 May 2017 15:01:52 +0200 Subject: [PATCH] Bug 18697: Fix date calculations for weekly frequencies in Serials Content-Type: text/plain; charset=utf-8 Same solution applied as in bug 18356/18607. Consistency++ The code in _get_next_date_week is again very similar to the code in _get_next_date_month or _get_next_date_year. I will not merge them here, but we could consider that in the future. Code in GetFictiveIssueNo has been adjusted similarly to month and year. It might be interesting to merge it with the code for unit 'day'. Test plan: [1] Do not apply this patch. Create a subscription for 3/week. When the first issue date is on a Saturday or Sunday, the intervals in the prediction pattern are 0,0,7,0,0,7,etc. Starting on Wed-Fri 1,1,5,etc. Starting on Mon-Tue 2,2,3,etc. [2] Apply this patch. Check again. The interval should be always 2,2,3 now and no longer depend on the day_of_week of first issue date. [3] Check another weekly frequency with multiple units per issue. Say 1 issue/3 weeks. Signed-off-by: Marcel de Rooy --- C4/Serials.pm | 57 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/C4/Serials.pm b/C4/Serials.pm index 1e5785b..36a77c4 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -2291,10 +2291,25 @@ sub GetFictiveIssueNumber { if($unit eq 'day') { $delta = Delta_Days($fa_year, $fa_month, $fa_day, $year, $month, $day); } elsif($unit eq 'week') { - ($wkno, $year) = Week_of_Year($year, $month, $day); - my ($fa_wkno, $fa_yr) = Week_of_Year($fa_year, $fa_month, $fa_day); - $delta = ($fa_yr == $year) ? ($wkno - $fa_wkno) : ( ($year-$fa_yr-1)*52 + (52-$fa_wkno+$wkno) ); - + $delta = Delta_Days($fa_year, $fa_month, $fa_day, $year, $month, $day); + if( $frequency->{issuesperunit} > 1 ) { + $issueno = 1 + int( $delta / 7) * $frequency->{'issuesperunit'}; + # Now calculate issues within last (incomplete) unit + $delta = $delta % 7; + my $incr = $unit eq 'week' ? 7 : 1; + $incr = int( $incr / $frequency->{issuesperunit} ); + if( $incr > 0 ) { + $delta = int( $delta / $incr ); + $delta = $delta < $frequency->{issuesperunit} ? $delta : $frequency->{issuesperunit} - 1; + } else { + $delta = $frequency->{issuesperunit} - 1; + } + $issueno += $delta; + } else { + $delta = int( $delta / 7 ); + $issueno = 1 + int( $delta / $frequency->{'unitsperissue'} ); + } + return $issueno; } elsif( $unit eq 'month' || $unit eq 'year' ) { $delta = _delta_units( [$fa_year, $fa_month, $fa_day], [$year, $month, $day], $unit ); if( $frequency->{issuesperunit} > 1 ) { @@ -2365,26 +2380,26 @@ sub _get_next_date_day { sub _get_next_date_week { my ($subscription, $freqdata, $year, $month, $day) = @_; - my ($wkno, $yr) = Week_of_Year($year, $month, $day); - my $fa_dow = Day_of_Week(split /-/, $subscription->{firstacquidate}); + my @newissue; # ( yy, mm, dd ) + my $delta_days = int( 7 / $freqdata->{issuesperunit} ); - if ($subscription->{countissuesperunit} + 1 > $freqdata->{issuesperunit}){ - $subscription->{countissuesperunit} = 1; - $wkno += $freqdata->{unitsperissue}; - if($wkno > 52){ - $wkno = $wkno % 52; - $yr++; - } - ($year,$month,$day) = Monday_of_Week($wkno, $yr); - ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $fa_dow - 1); - } else { - # Try to guess the next day of week - my $delta_days = int((7 - ($fa_dow - 1)) / $freqdata->{issuesperunit}); - ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $delta_days); + if( $freqdata->{issuesperunit} == 1 ) { + # Add full weeks (of 7 days) + @newissue = Add_Delta_Days( + $year, $month, $day, 7 * $freqdata->{"unitsperissue"} ); + } elsif ( $subscription->{countissuesperunit} < $freqdata->{issuesperunit} ) { + # Add rounded number of days based on frequency. + @newissue = Add_Delta_Days( $year, $month, $day, $delta_days ); $subscription->{countissuesperunit}++; + } else { + # We finished a cycle of issues within a unit. + # Subtract delta * (issues - 1), add 1 week + @newissue = Add_Delta_Days( $year, $month, $day, + -$delta_days * ($freqdata->{issuesperunit} - 1) ); + @newissue = Add_Delta_Days( @newissue, 7 ); + $subscription->{countissuesperunit} = 1; } - - return ($year, $month, $day); + return @newissue; } sub _get_next_date_month { -- 2.1.4