package ONO::Lib::DateTime::Calendar;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2000-2025 Jos KIRPS [ www.kirps.com | jos_AT_kirps_DOT_com ]
# and The Joopita Project [ www.joopita.org | contact_AT_joopita_DOT_com ]
#
# This file, as well as other parts of the ONO Software Project or related
# elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################
use strict;
use ONO::Lib::Basic;
use ONO::Lib::DateTime::ToolBox;
###############################################################################
# draw a complete calendar
###############################################################################
sub calendar {
my (
$self,
$mode,
$in_year,
$in_mon,
$in_mday,
$in_link,
$in_high,
$lang,
$style,
$header,
$out_link,
) = @_;
#: Display a calendar.
my $out_link2;
if ($out_link) {
$out_link2 = "$out_link?";
if ($out_link =~ /\?/) {
$out_link2 = "$out_link&";
}
$out_link2 .= "calendar_view=day&calendar_year=$in_year&calendar_month=$in_mon&calendar_day";
}
$in_high = ",$in_high,";
my $status;
my $cal;
my @days=qw(Mo Tu We Th Fr Sa Su);
if ($lang eq "de") {
@days=qw(Mo Di Mi Do Fr Sa So);
}
if ($lang eq "fr") {
@days=qw(Lu Ma Me Je Ve Sa Di);
}
if ($lang eq "lu") {
@days=qw(Mé De Më Do Fr Sa So);
}
if ($mode eq "month" || $mode eq "month:current") {
my ($status,$first,$last) = &monthframe("",$in_year,$in_mon);
$cal = qq~<table class="wide_table">
<tr class="bg_title">
~;
foreach my $day (@days) {
$cal .= qq~ <td class="pad10_2 tar">$day</td>~;
}
$cal .= qq~ </tr>~;
my ($counter,$exit,$sub);
for (my $w = 0; $w < 6; $w++) {
if (!$exit && $counter < $last) {
$cal .= qq~ <tr class="bb bl br">~;
if ($w == 0) {
if (!$first) {
$cal .= qq~ <td></td><td></td><td></td><td></td><td></td><td></td><td class="bg_paper bt bb bl br">1</td>
</tr>
<tr class="bl br">
~;
$counter++;
$sub = 1;
}
for (my $i = 1; $i < $first; $i++) {
$cal .= qq~ <td></td>~;
}
for (my $i = $first; $i < 8-$sub; $i++) {
$counter++;
my $show = $counter;
if ($in_link) {
$show = qq~<a href="$in_link&###SEMICOLON###calendar_view=day&###SEMICOLON###calendar_year=$in_year&###SEMICOLON###calendar_month=$in_mon&###SEMICOLON###calendar_day=$counter" class="col3">$counter</a>~;
}
if ($out_link) {
$show = qq~<a href="$out_link2=$counter" style="color:inherit">$counter</a>~;
}
if ($counter == $in_mday && $mode eq "month:current") {
$cal .= qq~<td class="pad10_2 bg_paper bt bb bl br tar bg_yellow"><strong>$show</strong></td>~;
} else {
if ($in_high =~ /\,$counter\,/ || $in_high =~ /\,0$counter\,/) {
$cal .= qq~<td class="pad10_2 bg_paper bt bb bl br tar bg_green"><strong>$show</strong></td>~;
} else {
$cal .= qq~<td class="pad10_2 bg_paper bt bb bl br tar">$show</td>~;
}
}
}
} else {
for (my $i = 1; $i < 8; $i++) {
$counter++;
if ($counter <= $last) {
my $show = $counter;
if ($in_link) {
$show = qq~<a href="$in_link&###SEMICOLON###calendar_view=day&###SEMICOLON###calendar_year=$in_year&###SEMICOLON###calendar_month=$in_mon&###SEMICOLON###calendar_day=$counter" class="col3">$counter</a>~;
}
if ($out_link) {
$show = qq~<a href="$out_link2=$counter" style="color:inherit">$counter</a>~;
}
if ($counter == $in_mday && $mode eq "month:current") {
$cal .= qq~<td class="pad10_2 bg_paper bt bb bl br tar bg_yellow"><strong>$show</strong></td>~;
} else {
if ($in_high =~ /\,$counter\,/ || $in_high =~ /\,0$counter\,/) {
$cal .= qq~<td class="pad10_2 bg_paper bt bb bl br tar bg_green"><strong>$show</strong></td>~;
} else {
$cal .= qq~<td class="pad10_2 bg_paper bt bb bl br tar">$show</td>~;
}
}
} else {
$exit = 1;
$cal .= qq~<td></td>~;
}
}
}
$cal .= qq~</tr>~;
}
}
$cal .= qq~</table>~;
}
if ($mode eq "week") {
$cal = qq~<table class="wide_table bo">~;
$cal .= qq~ <tr class="bg_title"><td style="width:2%"></td>~;
for (my $d = 0; $d < 7; $d++) {
$cal .= qq~ <td class="bold center" style="width:14%">$days[$d]</td>~;
}
$cal .= qq~ </tr>~;
for (my $h = 8; $h < 23; $h++) {
my $BG="eeeeee";
if ($h%2 != 0) {$BG="cccccc"}
$cal .= qq~ <tr class="bb"><td class="pad10_2 tar">$h:00</td>~;
for (my $d = 0; $d < 7; $d++) {
$cal .= qq~<td></td>~;
}
$cal =~ s/;$//;
$cal .= qq~</tr>~;
}
$cal .= qq~</table>~;
}
if ($header) {
$header = qq~<div class="tal">$header</div>~;
if ($out_link) {
$header = qq~<a href="$out_link" style="color:inherit">$header</a>~;
}
}
return (
$status,
qq~<div class="box_paper tar">
$header
<div class="bg_fabric">$cal</div>
<div class="bg_paper bl br bb" style="height:1px"></div>
<div class="bg_paper bl br bb" style="height:1px"></div>
<div class="bg_paper bl br bb" style="height:1px"></div>
</div>
~,
);
}
###############################################################################
# detect the weekday for a specific date
###############################################################################
sub weekday {
my ($self,$in_year,$in_month,$in_day,$lang) = @_;
#: Calculate a weekday.
my ($status,$weekday);
my @days = ONO::Lib::DateTime::ToolBox->day_name("a",$lang);
my @lines = `cal $in_month $in_year`;
foreach my $line (@lines) {
$line =~ s~[^A-Za-z0-9\ ]~~g;
$line =~ s~[^0-9]~:~g;
$line = ONO::Lib::Basic->remove_doubles($line,":");
if ($line =~ m/^(1\d):/) {
my $sunday = $1;
my $use_day = $in_day - $sunday + 6;
my $whilecounter;
while ($use_day > 6 && $whilecounter < 1024) {
$whilecounter++;
$use_day = $use_day - 7;
}
while ($use_day < 0 && $whilecounter < 1024) {
$whilecounter++;
$use_day = $use_day + 7;
}
$weekday = $days[$use_day+1];
}
}
return ($status,$weekday);
}
###############################################################################
# detect all week dates (mom - sun) for a specific date, export as comma list
###############################################################################
sub weekdates {
my ($self,$in_year,$in_month,$in_day) = @_;
#: Calculate week dates.
my ($status,$weekdates);
my @max = ( '31','28','31',
'30','31','30',
'31','31','30',
'31','30','31'
);
if ($in_year%4 == 0) {
$max[1] = 29;
}
my @lines = `cal $in_month $in_year`;
foreach my $line (@lines) {
$line =~ s~[^A-Za-z0-9\ ]~~g;
$line =~ s~[^0-9]~:~g;
$line = ONO::Lib::Basic->remove_doubles($line,":");
if ($line =~ m/^(1\d):/) {
my $sunday = $1;
my $whilecounter;
while ($sunday > 0 && $whilecounter < 1024) {
$whilecounter++;
$sunday = $sunday - 7;
}
while ($sunday < $in_day && $whilecounter < 1024) {
$whilecounter++;
$sunday = $sunday + 7;
}
my $sunday = $sunday - 7;
for (my $i = 1; $i < 8; $i++) {
my $date = $sunday + $i;
my $month = $in_month;
if ($date > $max[$in_month-1]) {
$date = $date - $max[$in_month-1];
$month = $in_month+1;
}
if ($date < 1) {
$date = $date + $max[$in_month-2];
$month = $in_month-1;
}
$weekdates .= qq~$date:$month,~;
}
}
}
return ($status,$weekdates);
}
###############################################################################
# return the first an last positions of days in a month
###############################################################################
sub monthframe {
my ($self,$in_year,$in_mon) = @_;
#: Calculate month frame.
my ($status,$first);
my @lines = `cal $in_mon $in_year`;
foreach my $line (@lines) {
if ($line !~ /$in_year/ && $line =~ /[0-9]/) {
# very important - remove strange chars:
$line =~ s~[^0-9\ ]~~gi;
# warning: don't use simple negation in IF statement
# as $first must be allowed to be ZERO!
if ($first eq "") {
$line =~ s~ +~ ~g;
$line =~ s~^ ~~g;
my @dates = split(/ /,$line);
my $date_num = @dates;
$first = 7 - $date_num;
}
}
}
if ($first < 0) {
$first = 0;
}
my $last = 31;
if ($in_mon == 4 || $in_mon == 6 || $in_mon == 9 || $in_mon == 11) {$last = 30}
if ($in_mon == 2) {
$last = 28;
if (substr($in_year,2,2)%4 == 0) {$last = 29}
}
return ($status,$first,$last);
}
###############################################################################
# end of script
###############################################################################
1;
__END__