File Coverage

File:C4/Calendar.pm
Coverage:8.3%

linestmtbrancondsubtimecode
1package C4::Calendar;
2
3# This file is part of Koha.
4#
5# Koha is free software; you can redistribute it and/or modify it under the
6# terms of the GNU General Public License as published by the Free Software
7# Foundation; either version 2 of the License, or (at your option) any later
8# version.
9#
10# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along with
15# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
16# Suite 330, Boston, MA 02111-1307 USA
17
18
2
2
2
851
22
67
use strict;
19
2
2
2
25
17
115
use warnings;
20
2
2
2
21
13
183
use vars qw($VERSION @EXPORT);
21
22
2
2
2
18
12
158
use Carp;
23
2
2
2
85
2403
178
use Date::Calc qw( Date_to_Days Today);
24
25
2
2
2
153
3
22
use C4::Context;
26
27
2
2
2
12
2
17
use constant ISO_DATE_FORMAT => "%04d-%02d-%02d";
28 - 50
=head1 NAME

C4::Calendar::Calendar - Koha module dealing with holidays.

=head1 SYNOPSIS

    use C4::Calendar::Calendar;

=head1 DESCRIPTION

This package is used to deal with holidays. Through this package, you can set 
all kind of holidays for the library.

=head1 FUNCTIONS

=head2 new

  $calendar = C4::Calendar->new(branchcode => $branchcode);

Each library branch has its own Calendar.  
C<$branchcode> specifies which Calendar you want.

=cut
51
52sub new {
53
0
    my $classname = shift @_;
54
0
    my %options = @_;
55
0
    my $self = bless({}, $classname);
56
0
    foreach my $optionName (keys %options) {
57
0
        $self->{lc($optionName)} = $options{$optionName};
58    }
59
0
    defined($self->{branchcode}) or croak "No branchcode argument to new. Should be C4::Calendar->new(branchcode => \$branchcode)";
60
0
    $self->_init($self->{branchcode});
61
0
    return $self;
62}
63
64sub _init {
65
0
    my $self = shift @_;
66
0
    my $branch = shift;
67
0
    defined($branch) or die "No branchcode sent to _init"; # must test for defined here and above to allow ""
68
0
    my $dbh = C4::Context->dbh();
69
0
    my $repeatable = $dbh->prepare( 'SELECT *
70                                       FROM repeatable_holidays
71                                      WHERE ( branchcode = ? )
72                                        AND (ISNULL(weekday) = ?)' );
73
0
    $repeatable->execute($branch,0);
74
0
    my %week_days_holidays;
75
0
    while (my $row = $repeatable->fetchrow_hashref) {
76
0
        my $key = $row->{weekday};
77
0
        $week_days_holidays{$key}{title} = $row->{title};
78
0
        $week_days_holidays{$key}{description} = $row->{description};
79    }
80
0
    $self->{'week_days_holidays'} = \%week_days_holidays;
81
82
0
    $repeatable->execute($branch,1);
83
0
    my %day_month_holidays;
84
0
    while (my $row = $repeatable->fetchrow_hashref) {
85
0
        my $key = $row->{month} . "/" . $row->{day};
86
0
        $day_month_holidays{$key}{title} = $row->{title};
87
0
        $day_month_holidays{$key}{description} = $row->{description};
88
0
        $day_month_holidays{$key}{day} = sprintf("%02d", $row->{day});
89
0
        $day_month_holidays{$key}{month} = sprintf("%02d", $row->{month});
90    }
91
0
    $self->{'day_month_holidays'} = \%day_month_holidays;
92
93
0
    my $special = $dbh->prepare( 'SELECT day, month, year, title, description
94                                    FROM special_holidays
95                                   WHERE ( branchcode = ? )
96                                     AND (isexception = ?)' );
97
0
    $special->execute($branch,1);
98
0
    my %exception_holidays;
99
0
    while (my ($day, $month, $year, $title, $description) = $special->fetchrow) {
100
0
        $exception_holidays{"$year/$month/$day"}{title} = $title;
101
0
        $exception_holidays{"$year/$month/$day"}{description} = $description;
102
0
        $exception_holidays{"$year/$month/$day"}{date} =
103                sprintf(ISO_DATE_FORMAT, $year, $month, $day);
104    }
105
0
    $self->{'exception_holidays'} = \%exception_holidays;
106
107
0
    $special->execute($branch,0);
108
0
    my %single_holidays;
109
0
    while (my ($day, $month, $year, $title, $description) = $special->fetchrow) {
110
0
        $single_holidays{"$year/$month/$day"}{title} = $title;
111
0
        $single_holidays{"$year/$month/$day"}{description} = $description;
112
0
        $single_holidays{"$year/$month/$day"}{date} =
113                sprintf(ISO_DATE_FORMAT, $year, $month, $day);
114    }
115
0
    $self->{'single_holidays'} = \%single_holidays;
116
0
    return $self;
117}
118
119 - 125
=head2 get_week_days_holidays

   $week_days_holidays = $calendar->get_week_days_holidays();

Returns a hash reference to week days holidays.

=cut
126
127sub get_week_days_holidays {
128
0
    my $self = shift @_;
129
0
    my $week_days_holidays = $self->{'week_days_holidays'};
130
0
    return $week_days_holidays;
131}
132
133 - 139
=head2 get_day_month_holidays

   $day_month_holidays = $calendar->get_day_month_holidays();

Returns a hash reference to day month holidays.

=cut
140
141sub get_day_month_holidays {
142
0
    my $self = shift @_;
143
0
    my $day_month_holidays = $self->{'day_month_holidays'};
144
0
    return $day_month_holidays;
145}
146
147 - 155
=head2 get_exception_holidays

    $exception_holidays = $calendar->exception_holidays();

Returns a hash reference to exception holidays. This kind of days are those
which stands for a holiday, but you wanted to make an exception for this particular
date.

=cut
156
157sub get_exception_holidays {
158
0
    my $self = shift @_;
159
0
    my $exception_holidays = $self->{'exception_holidays'};
160
0
    return $exception_holidays;
161}
162
163 - 170
=head2 get_single_holidays

    $single_holidays = $calendar->get_single_holidays();

Returns a hash reference to single holidays. This kind of holidays are those which
happend just one time.

=cut
171
172sub get_single_holidays {
173
0
    my $self = shift @_;
174
0
    my $single_holidays = $self->{'single_holidays'};
175
0
    return $single_holidays;
176}
177
178 - 192
=head2 insert_week_day_holiday

    insert_week_day_holiday(weekday => $weekday,
                            title => $title,
                            description => $description);

Inserts a new week day for $self->{branchcode}.

C<$day> Is the week day to make holiday.

C<$title> Is the title to store for the holiday formed by $year/$month/$day.

C<$description> Is the description to store for the holiday formed by $year/$month/$day.

=cut
193
194sub insert_week_day_holiday {
195
0
    my $self = shift @_;
196
0
    my %options = @_;
197
198
0
    my $weekday = $options{weekday};
199
0
    croak "Invalid weekday $weekday" unless $weekday =~ m/^[0-6]$/;
200
201
0
    my $dbh = C4::Context->dbh();
202
0
    my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (id,branchcode,weekday,day,month,title,description) values ( '',?,?,NULL,NULL,?,? )");
203
0
        $insertHoliday->execute( $self->{branchcode}, $weekday, $options{title}, $options{description});
204
0
    $self->{'week_days_holidays'}->{$weekday}{title} = $options{title};
205
0
    $self->{'week_days_holidays'}->{$weekday}{description} = $options{description};
206
0
    return $self;
207}
208
209 - 226
=head2 insert_day_month_holiday

    insert_day_month_holiday(day => $day,
                             month => $month,
                             title => $title,
                             description => $description);

Inserts a new day month holiday for $self->{branchcode}.

C<$day> Is the day month to make the date to insert.

C<$month> Is month to make the date to insert.

C<$title> Is the title to store for the holiday formed by $year/$month/$day.

C<$description> Is the description to store for the holiday formed by $year/$month/$day.

=cut
227
228sub insert_day_month_holiday {
229
0
    my $self = shift @_;
230
0
    my %options = @_;
231
232
0
    my $dbh = C4::Context->dbh();
233
0
    my $insertHoliday = $dbh->prepare("insert into repeatable_holidays (id,branchcode,weekday,day,month,title,description) values ('', ?, NULL, ?, ?, ?,? )");
234
0
        $insertHoliday->execute( $self->{branchcode}, $options{day},$options{month},$options{title}, $options{description});
235
0
    $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{title} = $options{title};
236
0
    $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{description} = $options{description};
237
0
    return $self;
238}
239
240 - 260
=head2 insert_single_holiday

    insert_single_holiday(day => $day,
                          month => $month,
                          year => $year,
                          title => $title,
                          description => $description);

Inserts a new single holiday for $self->{branchcode}.

C<$day> Is the day month to make the date to insert.

C<$month> Is month to make the date to insert.

C<$year> Is year to make the date to insert.

C<$title> Is the title to store for the holiday formed by $year/$month/$day.

C<$description> Is the description to store for the holiday formed by $year/$month/$day.

=cut
261
262sub insert_single_holiday {
263
0
    my $self = shift @_;
264
0
    my %options = @_;
265
266
0
    @options{qw(year month day)} = ( $options{date} =~ m/(\d+)-(\d+)-(\d+)/o )
267      if $options{date} && !$options{day};
268
269
0
        my $dbh = C4::Context->dbh();
270
0
    my $isexception = 0;
271
0
    my $insertHoliday = $dbh->prepare("insert into special_holidays (id,branchcode,day,month,year,isexception,title,description) values ('', ?,?,?,?,?,?,?)");
272
0
        $insertHoliday->execute( $self->{branchcode}, $options{day},$options{month},$options{year}, $isexception, $options{title}, $options{description});
273
0
    $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
274
0
    $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
275
0
    return $self;
276}
277
278 - 298
=head2 insert_exception_holiday

    insert_exception_holiday(day => $day,
                             month => $month,
                             year => $year,
                             title => $title,
                             description => $description);

Inserts a new exception holiday for $self->{branchcode}.

C<$day> Is the day month to make the date to insert.

C<$month> Is month to make the date to insert.

C<$year> Is year to make the date to insert.

C<$title> Is the title to store for the holiday formed by $year/$month/$day.

C<$description> Is the description to store for the holiday formed by $year/$month/$day.

=cut
299
300sub insert_exception_holiday {
301
0
    my $self = shift @_;
302
0
    my %options = @_;
303
304
0
    @options{qw(year month day)} = ( $options{date} =~ m/(\d+)-(\d+)-(\d+)/o )
305      if $options{date} && !$options{day};
306
307
0
    my $dbh = C4::Context->dbh();
308
0
    my $isexception = 1;
309
0
    my $insertException = $dbh->prepare("insert into special_holidays (id,branchcode,day,month,year,isexception,title,description) values ('', ?,?,?,?,?,?,?)");
310
0
        $insertException->execute( $self->{branchcode}, $options{day},$options{month},$options{year}, $isexception, $options{title}, $options{description});
311
0
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
312
0
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
313
0
    return $self;
314}
315
316 - 328
=head2 ModWeekdayholiday

    ModWeekdayholiday(weekday =>$weekday,
                      title => $title,
                      description => $description)

Modifies the title and description of a weekday for $self->{branchcode}.

C<$weekday> Is the title to update for the holiday.

C<$description> Is the description to update for the holiday.

=cut
329
330sub ModWeekdayholiday {
331
0
    my $self = shift @_;
332
0
    my %options = @_;
333
334
0
    my $dbh = C4::Context->dbh();
335
0
    my $updateHoliday = $dbh->prepare("UPDATE repeatable_holidays SET title = ?, description = ? WHERE branchcode = ? AND weekday = ?");
336
0
    $updateHoliday->execute( $options{title},$options{description},$self->{branchcode},$options{weekday});
337
0
    $self->{'week_days_holidays'}->{$options{weekday}}{title} = $options{title};
338
0
    $self->{'week_days_holidays'}->{$options{weekday}}{description} = $options{description};
339
0
    return $self;
340}
341
342 - 359
=head2 ModDaymonthholiday

    ModDaymonthholiday(day => $day,
                       month => $month,
                       title => $title,
                       description => $description);

Modifies the title and description for a day/month holiday for $self->{branchcode}.

C<$day> The day of the month for the update.

C<$month> The month to be used for the update.

C<$title> The title to be updated for the holiday.

C<$description> The description to be update for the holiday.

=cut
360
361sub ModDaymonthholiday {
362
0
    my $self = shift @_;
363
0
    my %options = @_;
364
365
0
    my $dbh = C4::Context->dbh();
366
0
    my $updateHoliday = $dbh->prepare("UPDATE repeatable_holidays SET title = ?, description = ? WHERE month = ? AND day = ? AND branchcode = ?");
367
0
       $updateHoliday->execute( $options{title},$options{description},$options{month},$options{day},$self->{branchcode});
368
0
    $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{title} = $options{title};
369
0
    $self->{'day_month_holidays'}->{"$options{month}/$options{day}"}{description} = $options{description};
370
0
    return $self;
371}
372
373 - 393
=head2 ModSingleholiday

    ModSingleholiday(day => $day,
                     month => $month,
                     year => $year,
                     title => $title,
                     description => $description);

Modifies the title and description for a single holiday for $self->{branchcode}.

C<$day> Is the day of the month to make the update.

C<$month> Is the month to make the update.

C<$year> Is the year to make the update.

C<$title> Is the title to update for the holiday formed by $year/$month/$day.

C<$description> Is the description to update for the holiday formed by $year/$month/$day.

=cut
394
395sub ModSingleholiday {
396
0
    my $self = shift @_;
397
0
    my %options = @_;
398
399
0
    my $dbh = C4::Context->dbh();
400
0
    my $isexception = 0;
401
0
    my $updateHoliday = $dbh->prepare("UPDATE special_holidays SET title = ?, description = ? WHERE day = ? AND month = ? AND year = ? AND branchcode = ? AND isexception = ?");
402
0
      $updateHoliday->execute($options{title},$options{description},$options{day},$options{month},$options{year},$self->{branchcode},$isexception);
403
0
    $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
404
0
    $self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
405
0
    return $self;
406}
407
408 - 428
=head2 ModExceptionholiday

    ModExceptionholiday(day => $day,
                        month => $month,
                        year => $year,
                        title => $title,
                        description => $description);

Modifies the title and description for an exception holiday for $self->{branchcode}.

C<$day> Is the day of the month for the holiday.

C<$month> Is the month for the holiday.

C<$year> Is the year for the holiday.

C<$title> Is the title to be modified for the holiday formed by $year/$month/$day.

C<$description> Is the description to be modified for the holiday formed by $year/$month/$day.

=cut
429
430sub ModExceptionholiday {
431
0
    my $self = shift @_;
432
0
    my %options = @_;
433
434
0
    my $dbh = C4::Context->dbh();
435
0
    my $isexception = 1;
436
0
    my $updateHoliday = $dbh->prepare("UPDATE special_holidays SET title = ?, description = ? WHERE day = ? AND month = ? AND year = ? AND branchcode = ? AND isexception = ?");
437
0
    $updateHoliday->execute($options{title},$options{description},$options{day},$options{month},$options{year},$self->{branchcode},$isexception);
438
0
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{title} = $options{title};
439
0
    $self->{'exception_holidays'}->{"$options{year}/$options{month}/$options{day}"}{description} = $options{description};
440
0
    return $self;
441}
442
443 - 460
=head2 delete_holiday

    delete_holiday(weekday => $weekday
                   day => $day,
                   month => $month,
                   year => $year);

Delete a holiday for $self->{branchcode}.

C<$weekday> Is the week day to delete.

C<$day> Is the day month to make the date to delete.

C<$month> Is month to make the date to delete.

C<$year> Is year to make the date to delete.

=cut
461
462sub delete_holiday {
463
0
    my $self = shift @_;
464
0
    my %options = @_;
465
466    # Verify what kind of holiday that day is. For example, if it is
467    # a repeatable holiday, this should check if there are some exception
468        # for that holiday rule. Otherwise, if it is a regular holiday, it´s
469    # ok just deleting it.
470
471
0
    my $dbh = C4::Context->dbh();
472
0
    my $isSingleHoliday = $dbh->prepare("SELECT id FROM special_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?) AND (year = ?)");
473
0
    $isSingleHoliday->execute($self->{branchcode}, $options{day}, $options{month}, $options{year});
474
0
    if ($isSingleHoliday->rows) {
475
0
        my $id = $isSingleHoliday->fetchrow;
476
0
        $isSingleHoliday->finish; # Close the last query
477
478
0
        my $deleteHoliday = $dbh->prepare("DELETE FROM special_holidays WHERE id = ?");
479
0
        $deleteHoliday->execute($id);
480
0
        delete($self->{'single_holidays'}->{"$options{year}/$options{month}/$options{day}"});
481    } else {
482
0
        $isSingleHoliday->finish; # Close the last query
483
484
0
        my $isWeekdayHoliday = $dbh->prepare("SELECT id FROM repeatable_holidays WHERE branchcode = ? AND weekday = ?");
485
0
        $isWeekdayHoliday->execute($self->{branchcode}, $options{weekday});
486
0
        if ($isWeekdayHoliday->rows) {
487
0
            my $id = $isWeekdayHoliday->fetchrow;
488
0
            $isWeekdayHoliday->finish; # Close the last query
489
490
0
            my $updateExceptions = $dbh->prepare("UPDATE special_holidays SET isexception = 0 WHERE (WEEKDAY(CONCAT(special_holidays.year,'-',special_holidays.month,'-',special_holidays.day)) = ?) AND (branchcode = ?)");
491
0
            $updateExceptions->execute($options{weekday}, $self->{branchcode});
492
0
            $updateExceptions->finish; # Close the last query
493
494
0
            my $deleteHoliday = $dbh->prepare("DELETE FROM repeatable_holidays WHERE id = ?");
495
0
            $deleteHoliday->execute($id);
496
0
            delete($self->{'week_days_holidays'}->{$options{weekday}});
497        } else {
498
0
            $isWeekdayHoliday->finish; # Close the last query
499
500
0
            my $isDayMonthHoliday = $dbh->prepare("SELECT id FROM repeatable_holidays WHERE (branchcode = ?) AND (day = ?) AND (month = ?)");
501
0
            $isDayMonthHoliday->execute($self->{branchcode}, $options{day}, $options{month});
502
0
            if ($isDayMonthHoliday->rows) {
503
0
                my $id = $isDayMonthHoliday->fetchrow;
504
0
                $isDayMonthHoliday->finish;
505
0
                my $updateExceptions = $dbh->prepare("UPDATE special_holidays SET isexception = 0 WHERE (special_holidays.branchcode = ?) AND (special_holidays.day = ?) and (special_holidays.month = ?)");
506
0
                $updateExceptions->execute($self->{branchcode}, $options{day}, $options{month});
507
0
                $updateExceptions->finish; # Close the last query
508
509
0
                my $deleteHoliday = $dbh->prepare("DELETE FROM repeatable_holidays WHERE (id = ?)");
510
0
                $deleteHoliday->execute($id);
511
0
                delete($self->{'day_month_holidays'}->{"$options{month}/$options{day}"});
512            }
513        }
514    }
515
0
    return $self;
516}
517
518 - 528
=head2 isHoliday

    $isHoliday = isHoliday($day, $month $year);

C<$day> Is the day to check whether if is a holiday or not.

C<$month> Is the month to check whether if is a holiday or not.

C<$year> Is the year to check whether if is a holiday or not.

=cut
529
530sub isHoliday {
531
0
    my ($self, $day, $month, $year) = @_;
532        # FIXME - date strings are stored in non-padded metric format. should change to iso.
533        # FIXME - should change arguments to accept C4::Dates object
534
0
        $month=$month+0;
535
0
        $year=$year+0;
536
0
        $day=$day+0;
537
0
    my $weekday = &Date::Calc::Day_of_Week($year, $month, $day) % 7;
538
0
    my $weekDays = $self->get_week_days_holidays();
539
0
    my $dayMonths = $self->get_day_month_holidays();
540
0
    my $exceptions = $self->get_exception_holidays();
541
0
    my $singles = $self->get_single_holidays();
542
0
    if (defined($exceptions->{"$year/$month/$day"})) {
543
0
        return 0;
544    } else {
545
0
        if ((exists($weekDays->{$weekday})) ||
546            (exists($dayMonths->{"$month/$day"})) ||
547            (exists($singles->{"$year/$month/$day"}))) {
548
0
                  return 1;
549        } else {
550
0
            return 0;
551        }
552    }
553
554}
555
556 - 560
=head2 copy_to_branch

    $calendar->copy_to_branch($target_branch)

=cut
561
562sub copy_to_branch {
563
0
    my ($self, $target_branch) = @_;
564
565
0
    croak "No target_branch" unless $target_branch;
566
567
0
    my $target_calendar = C4::Calendar->new(branchcode => $target_branch);
568
569
0
    my ($y, $m, $d) = Today();
570
0
    my $today = sprintf ISO_DATE_FORMAT, $y,$m,$d;
571
572
0
    my $wdh = $self->get_week_days_holidays;
573
0
    $target_calendar->insert_week_day_holiday( weekday => $_, %{ $wdh->{$_} } )
574
0
0
      foreach keys %$wdh;
575
0
    $target_calendar->insert_day_month_holiday(%$_)
576
0
0
      foreach values %{ $self->get_day_month_holidays };
577
0
    $target_calendar->insert_exception_holiday(%$_)
578
0
0
0
      foreach grep { $_->{date} gt $today } values %{ $self->get_exception_holidays };
579
0
    $target_calendar->insert_single_holiday(%$_)
580
0
0
0
      foreach grep { $_->{date} gt $today } values %{ $self->get_single_holidays };
581
582
0
    return 1;
583}
584
585 - 593
=head2 addDate

    my ($day, $month, $year) = $calendar->addDate($date, $offset)

C<$date> is a C4::Dates object representing the starting date of the interval.

C<$offset> Is the number of days that this function has to count from $date.

=cut
594
595sub addDate {
596
0
    my ($self, $startdate, $offset) = @_;
597
0
    my ($year,$month,$day) = split("-",$startdate->output('iso'));
598
0
        my $daystep = 1;
599
0
        if ($offset < 0) { # In case $offset is negative
600       # $offset = $offset*(-1);
601
0
                $daystep = -1;
602    }
603
0
        my $daysMode = C4::Context->preference('useDaysMode');
604
0
    if ($daysMode eq 'Datedue') {
605
0
        ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $offset );
606
0
          while ($self->isHoliday($day, $month, $year)) {
607
0
            ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $daystep);
608        }
609    } elsif($daysMode eq 'Calendar') {
610
0
        while ($offset != 0) {
611
0
            ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $daystep);
612
0
            if (!($self->isHoliday($day, $month, $year))) {
613
0
                $offset = $offset - $daystep;
614                        }
615        }
616        } else { ## ($daysMode eq 'Days')
617
0
        ($year, $month, $day) = &Date::Calc::Add_Delta_Days($year, $month, $day, $offset );
618    }
619
0
    return(C4::Dates->new( sprintf(ISO_DATE_FORMAT,$year,$month,$day),'iso'));
620}
621
622 - 630
=head2 daysBetween

    my $daysBetween = $calendar->daysBetween($startdate, $enddate)

C<$startdate> and C<$enddate> are C4::Dates objects that define the interval.

Returns the number of non-holiday days in the interval.
useDaysMode syspref has no effect here.
=cut
631
632sub daysBetween {
633
0
    my $self = shift or return;
634
0
    my $startdate = shift or return;
635
0
    my $enddate = shift or return;
636
0
    my ($yearFrom,$monthFrom,$dayFrom) = split("-",$startdate->output('iso'));
637
0
    my ($yearTo, $monthTo, $dayTo ) = split("-", $enddate->output('iso'));
638
0
    if (Date_to_Days($yearFrom,$monthFrom,$dayFrom) > Date_to_Days($yearTo,$monthTo,$dayTo)) {
639
0
        return 0;
640        # we don't go backwards ( FIXME - handle this error better )
641    }
642
0
    my $count = 0;
643
0
    while (1) {
644
0
        ($yearFrom != $yearTo or $monthFrom != $monthTo or $dayFrom != $dayTo) or last; # if they all match, it's the last day
645
0
        unless ($self->isHoliday($dayFrom, $monthFrom, $yearFrom)) {
646
0
            $count++;
647        }
648
0
        ($yearFrom, $monthFrom, $dayFrom) = &Date::Calc::Add_Delta_Days($yearFrom, $monthFrom, $dayFrom, 1);
649    }
650
0
    return($count);
651}
652
6531;
654