package Calendar::List; use strict; use warnings; use vars qw($VERSION @ISA %EXPORT_TAGS @EXPORT_OK @EXPORT); $VERSION = '0.22'; #---------------------------------------------------------------------------- =head1 NAME Calendar::List - A module for creating date lists =head1 SYNOPSIS use Calendar::List; # basic usage my %hash = calendar_list('DD-MM-YYYY' => 'DD MONTH, YYYY' ); my @list = calendar_list('MM-DD-YYYY'); my $html = calendar_selectbox('DD-MM-YYYY' => 'DAY DDEXT MONTH, YYYY'); # using the hash my %hash01 = ( 'options' => 10, 'exclude' => { 'weekend' => 1 }, 'start' => '01-05-2003', ); my %hash02 = ( 'options' => 10, 'exclude' => { 'holidays' => \@holidays }, 'start' => '01-05-2003', ); my %hash03 = ( 'exclude' => { 'monday' => 1, 'tuesday' => 1, 'wednesday' => 1 }, 'start' => '01-05-2003', 'end' => '10-05-2003', 'name' => 'MyDates', 'selected' => '04-05-2003', ); my %hash = calendar_list('DD-MM-YYYY' => 'DDEXT MONTH YYYY', \%hash01); my @list = calendar_list('DD-MM-YYYY', \%hash02); my $html = calendar_selectbox('DD-MM-YYYY',\%hash03); =head1 DESCRIPTION The module is intended to be used to return a simple list, hash or scalar of calendar dates. This is achieved by two functions, calendar_list and calendar_selectbox. The former allows a return of a list of dates and a hash of dates, whereas the later returns a scalar containing a HTML code snippet for use as a HTML Form field select box. =head1 EXPORT calendar_list, calendar_selectbox =cut #---------------------------------------------------------------------------- ############################################################################# #Export Settings # ############################################################################# require Exporter; @ISA = qw(Exporter); %EXPORT_TAGS = ( 'all' => [ qw( calendar_list calendar_selectbox ) ] ); @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); @EXPORT = ( @{ $EXPORT_TAGS{'all'} } ); ############################################################################# #Library Modules # ############################################################################# use Calendar::Functions qw(:all); use Clone qw(clone); use Tie::IxHash; ############################################################################# #Variables ############################################################################# # prime our print out names my @dotw = qw( Sunday Monday Tuesday Wednesday Thursday Friday Saturday ); # THE DEFAULTS my $Format = 'DD-MM-YYYY'; my @order = qw( day month year ); my %Defaults = ( maxcount => 30, selectname => 'calendar', selected => [], startdate => undef, enddate => undef, start => [1,1,1970], end => [31,12,2037], exclude => [ 0,0,0,0,0,0,0,0 ], holidays => {}, ); my (%Settings); #---------------------------------------------------------------------------- ############################################################################# #Interface Functions # ############################################################################# =head1 FUNCTIONS =over 4 =item calendar_list([DATEFORMAT] [,DATEFORMAT] [,OPTIONSHASH]) Returns a list in an array context or a hash reference in any other context. All paramters are optional, one or two date formats can be specified for the date formats returned in the list/hash. A hash of user defined settings can also be passed into the function. See below for further details. Note that a second date format is not required when returning a list. A single date format when returning a hash reference, will be used in both key and value portions. =cut sub calendar_list { my $wantarray = (@_ < 2 || ref($_[1]) eq 'HASH') ? 1 : 0; my ($fmt1,$fmt2,$hash) = _thelist(@_); return _callist($fmt1,$fmt2,$hash,$wantarray); } =item calendar_selectbox([DATEFORMAT] [,DATEFORMAT] [,OPTIONSHASH]) Returns a scalar containing a HTML string. The HTML snippet consists of an HTML form field select box. All paramters are optional, one or two date formats can be specified for the date formats returned in the value attribute and data portion. A hash of user defined settings can also be passed into the function. See below for further details. Note that a single date format will be used in both value attribute and data portions. =cut sub calendar_selectbox { my ($fmt1,$fmt2,$hash) = _thelist(@_); return _calselect($fmt1,$fmt2,$hash); } ############################################################################# #Internal Functions # ############################################################################# # name: _thelist # args: format string 1 .... optional # format string 2 .... optional # settings hash ...... optional # retv: undef if invalid settings, otherwise a hash of dates, keyed by # an incremental counter. # desc: The heart of the engine. Arranges the parameters passed to the # the interface function, calls for the settings to be decided, # them creates the main hash table of dates. # Stops when either the end date is reached, or the maximum number # of entries have been found. sub _thelist { my $format1 = shift unless(ref($_[0]) eq 'HASH'); my $format2 = shift unless(ref($_[0]) eq 'HASH'); my $usrhash = shift if(ref($_[0]) eq 'HASH'); $format1 = $Format unless($format1); $format2 = $format1 unless($format2); return if _setargs($usrhash,$format1); $Settings{nowdate} = $Settings{startdate}; my $optcount = 0; # our option counter my %DateHash; tie(%DateHash, 'Tie::IxHash'); while($optcount < $Settings{maxcount}) { my ($nowday,$nowmon,$nowyear,$nowdow) = decode_date($Settings{nowdate}); # ignore days we're not interested in unless($Settings{exclude}->[$nowdow]) { my $fdate = sprintf "%02d-%02d-%04d", $nowday,$nowmon,$nowyear; unless($Settings{exclude}->[7] && $Settings{holidays} && $Settings{holidays}->{$fdate}) { # store date $DateHash{$optcount++} = [decode_date($Settings{nowdate})]; } } # stop if reached end date last if(compare_dates($Settings{nowdate},$Settings{enddate}) == 0); # increment $Settings{nowdate} = add_day($Settings{nowdate}); } return $format1,$format2,\%DateHash; } # name: _callist # args: format string 1 .... optional # format string 2 .... optional # settings hash ...... optional # retv: undef if invalid settings, otherwise an array if zero or one # date format provided, in ascending order, or a hash if two # date formats. # desc: The cream on top. Takes the hash provided by _thelist and uses # it to create a formatted array or hash. sub _callist { my ($fmt1,$fmt2,$hash,$wantarray) = @_; return unless($hash); my (@returns,%returns); tie(%returns, 'Tie::IxHash'); foreach my $key (sort {$a <=> $b} keys %$hash) { my $date1 = format_date($fmt1,@{$hash->{$key}}); if($wantarray) { push @returns, $date1; } else { my $date2 = format_date($fmt2,@{$hash->{$key}}); $returns{$date1} = $date2; } } #print STDERR "\n\n===[".scalar(each %returns)."]===\n\n"; return @returns if($wantarray); #use Data::Dumper qw(DumperX); #open FH, ">>trace.log" or die "cannot open file:$!\n"; #print FH "STORED:\n".DumperX(\%returns)."\n"; #close FH; #exit; # while(my (@temp) = each %returns) { # push @returns, @temp; # } # map { push @returns, $_->[0],$_->[1] } each %returns; # return @returns; return %returns; } # name: _calselect # args: format string 1 .... optional # format string 2 .... optional # settings hash ...... optional # retv: undef if invalid settings, otherwise a hash of dates, keyed by # an incremental counter. # desc: The cream on top. Takes the hash provided by _thelist and uses # it to create a HTML select box form field, making use of any # user defined settings. sub _calselect { my ($fmt1,$fmt2,$hash) = @_; return unless($hash); # open SELECT tag my $select = "