package Book::Calendar; use Date::Calc (); my %HTML_CAL_CACHE = (); my %TXT_CAL_CACHE = (); my $CURRENT_MONTH_LAST_CACHED_DAY = 0; use constant DEBUG => 0; # prebuild this month's, 3 months back and 1 month forward calendars my($cyear, $cmonth) = Date::Calc::Today(); for my $i (-3..1) { my($year, $month) = Date::Calc::Add_Delta_YMD($cyear, $cmonth, 1, 0, $i, 0); my $cal = ''; get_html_calendar(\$cal, $year, $month); # disregard the returned calendar } # $cal = create_text_calendar($year, $month); # the created calendar is cached ###################### sub get_text_calendar { my($year,$month) = @_; unless ($TXT_CAL_CACHE{$year}{$month}) { $TXT_CAL_CACHE{$year}{$month} = Date::Calc::Calendar($year, $month); # remove extra new line at the end chomp $TXT_CAL_CACHE{$year}{$month}; } return $TXT_CAL_CACHE{$year}{$month}; } # get_html_calendar(\$calendar,1999,7); ###################### sub get_html_calendar { my $r_calendar = shift; my $year = shift || 1; my $month = shift || 1; my($cur_year, $cur_month, $cur_day) = Date::Calc::Today(); # should requested calendar be updated if it exists already? my $must_update_current_month_cache = 0; for my $i (-1..1) { my ($t_year, $t_month) = Date::Calc::Add_Delta_YMD($year, $month, 1, 0, $i, 0); $must_update_current_month_cache = 1 if $t_year == $cur_year and $t_month == $cur_month and $CURRENT_MONTH_LAST_CACHED_DAY < $cur_day; last if $must_update_current_month_cache; } unless (exists $HTML_CAL_CACHE{$year}{$month} and not $must_update_current_month_cache) { warn "creating a new calendar for $year $month\n" if DEBUG; my @cal = (); for my $i (-1..1) { my $id = $i+1; my ($t_year, $t_month) = Date::Calc::Add_Delta_YMD($year, $month, 1, 0, $i, 0); # link the calendar from passed month $cal[$id] = get_text_calendar($t_year, $t_month); # get a copy my $yearmonth = sprintf("%0.4d%0.2d", $t_year, $t_month); my $cur_yearmonth = sprintf("%0.4d%0.2d", $cur_year, $cur_month); # tri-state: ppf (past/present/future) my $ppf = $yearmonth <=> $cur_yearmonth; $cal[$id] =~ s{(\s\d|\b\d\d)\b} {link_days($1, $yearmonth, $ppf, $cur_day)}eg; } # cache the html calendar for future use $HTML_CAL_CACHE{$year}{$month} = qq{
$cal[0]
$cal[1]
$cal[2]
}; $CURRENT_MONTH_LAST_CACHED_DAY = $cur_day if $must_update_current_month_cache; } $$r_calendar = $HTML_CAL_CACHE{$year}{$month}; } # end of sub calendar # # link_days($token,199901,1,10); ########### sub link_days { my($token, $yearmonth, $ppf, $cur_day) = @_; # $cur_day relevant only if $ppf == 0 # skip non-days (non (\d or \d\d) ) return $token unless my ($c1, $c2) = $token =~ /(\s|\d)(\d)/; my($fill, $day) = ($c1 =~ /\d/) ? ('', $c1.$c2) : ($c1, $c2) ; # don't link days in the future return $token if $ppf == 1 or ($ppf == 0 and $day > $cur_day); # link the date with placeholders to be replaced later return qq{$fill$day}; } # end of sub link_days # replace the placeholders with live data # customize_calendar(\$calendar,$url,$params); ####################### sub customize_calendar { my $r_calendar = shift; my $url = shift || ''; my $params = shift || ''; my %map = ( URL => $url, PARAMS => $params, ); $$r_calendar =~ s/\[(\w+)\]/$map{$1}/g; } # end of sub calendar 1;