@@ -, +, @@ Serials subscription with first issue on Feb 21 and 5 per month. The first issues will be 21, 22, 23, 24, 25. Then jumping to 21, 23, 25, etc. see 6 day intervals and a new cycle starting on the 21st. So Feb 21, 27, Mar 5, 11, 17 and Mar 21, 27, etc. --- C4/Serials.pm | 72 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 24 deletions(-) --- a/C4/Serials.pm +++ a/C4/Serials.pm @@ -2294,17 +2294,18 @@ sub GetFictiveIssueNumber { ($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) ); - } elsif($unit eq 'month') { - $delta = ($fa_year == $year) - ? ($month - $fa_month) - : ( ($year-$fa_year-1)*12 + (12-$fa_month+$month) ); - } elsif( $unit eq 'year' ) { - ( $delta ) = N_Delta_YMD( $fa_year, $fa_month, $fa_day, $year, $month, $day ); + + } elsif( $unit eq 'month' || $unit eq 'year' ) { + $delta = _delta_units( [$fa_year, $fa_month, $fa_day], [$year, $month, $day], $unit ); if( $frequency->{issuesperunit} > 1 ) { $issueno = 1 + $delta * $frequency->{'issuesperunit'}; - my @fa_upd = Add_Delta_YM( $fa_year, $fa_month, $fa_day, $delta, 0 ); - $delta = Delta_Days( @fa_upd, $year, $month, $day ); - my $incr = int( 365 / $frequency->{issuesperunit} ); + # Now calculate issues within last (incomplete) unit + $delta = Delta_Days( + Add_Delta_YM( $fa_year, $fa_month, $fa_day, + $unit eq 'month' ? ( 0, $delta ) : ( $delta, 0 )), + $year, $month, $day ); + my $incr = $unit eq 'month' ? 30 : 365; + $incr = int( $incr / $frequency->{issuesperunit} ); if( $incr > 0 ) { $delta = int( $delta / $incr ); $delta = $delta < $frequency->{issuesperunit} ? $delta : $frequency->{issuesperunit} - 1; @@ -2327,6 +2328,27 @@ sub GetFictiveIssueNumber { return $issueno; } +sub _delta_units { +# wrapper around N_Delta_YMD +# Note that N_Delta_YMD returns 29 days between e.g. 22-2-72 and 22-3-72 +# while we expect 1 month. + my ( $date1, $date2, $unit ) = @_; + my @delta = N_Delta_YMD( @$date1, @$date2 ); + if( $delta[2] > 27 ) { + # Check if we could add a month + my @jump = Add_Delta_YM( @$date1, $delta[0], 1 + $delta[1] ); + if( Delta_Days( @jump, @$date2 ) >= 0 ) { + $delta[1]++; + } + } + if( $delta[1] >= 12 ) { + $delta[0]++; + $delta[1] -= 12; + } + # if unit is year, we only return full years + return $unit eq 'month' ? $delta[0] * 12 + $delta[1] : $delta[0]; +} + sub _get_next_date_day { my ($subscription, $freqdata, $year, $month, $day) = @_; @@ -2368,24 +2390,26 @@ sub _get_next_date_week { sub _get_next_date_month { my ($subscription, $freqdata, $year, $month, $day) = @_; - my $fa_day; - (undef, undef, $fa_day) = split /-/, $subscription->{firstacquidate}; + my @newissue; # ( yy, mm, dd ) + my $delta_days = int( 30 / $freqdata->{issuesperunit} ); - if ($subscription->{countissuesperunit} + 1 > $freqdata->{issuesperunit}){ - $subscription->{countissuesperunit} = 1; - ($year,$month,$day) = Add_Delta_YM($year,$month,$day, 0, - $freqdata->{unitsperissue}); - my $days_in_month = Days_in_Month($year, $month); - $day = $fa_day <= $days_in_month ? $fa_day : $days_in_month; - } else { - # Try to guess the next day in month - my $days_in_month = Days_in_Month($year, $month); - my $delta_days = int(($days_in_month - ($fa_day - 1)) / $freqdata->{issuesperunit}); - ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $delta_days); + if( $freqdata->{issuesperunit} == 1 ) { + # Add full months + @newissue = Add_Delta_YM( + $year, $month, $day, 0, $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 month + @newissue = Add_Delta_Days( $year, $month, $day, + -$delta_days * ($freqdata->{issuesperunit} - 1) ); + @newissue = Add_Delta_YM( @newissue, 0, 1 ); + $subscription->{countissuesperunit} = 1; } - - return ($year, $month, $day); + return @newissue; } sub _get_next_date_year { --