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{
};
$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;