0

I'm creating a calendar with Sunday being the start of each week and I want to present the week number of the year before each row of dates.

This is my calendar

my calendar

How can I add week numbers like this:

This is what I need

My code:

<?php
function generate_calendar($month, $year) {
    $calendar = array();
    $days_in_month = cal_days_in_month(CAL_GREGORIAN, $month, $year);
    $first_day_of_month = date('w', strtotime("$year-$month-01"));
    $week_number = 1;
    $week = array();
    
    // Determine the week number offset
    $days_from_january_1st = strtotime("$year-01-01");
    $days_to_first_day_of_month = strtotime("$year-$month-01");
    $week_number_offset = floor(($days_to_first_day_of_month - $days_from_january_1st) / 604800);
    
    // Check if the last week of the previous month is full (7 days)
    $last_week_of_previous_month = $week_number_offset;

    if ($month > 1) {
        $previous_month = $month - 1;
        $previous_month_year = $year;

    $previous_month_year = date("Y", strtotime("-1 month" , strtotime("$year-$month-01")));
    $previous_month = date("n", strtotime("-1 month" , strtotime("$year-$month-01")));

        if ($previous_month == 0) {
            $previous_month = 12;
            $previous_month_year = $year - 1;
        }

        $days_in_previous_month = cal_days_in_month(CAL_GREGORIAN, $previous_month, $previous_month_year);
        $last_day_of_previous_month = date('w', strtotime("$previous_month_year-$previous_month-$days_in_previous_month"));
        if ($last_day_of_previous_month == 6) {
            $last_week_of_previous_month=$last_week_of_previous_month + 1;
        } else {
            // Check if the last week of the previous month only has a few days
            $last_week_of_previous_month = $last_week_of_previous_month;
        }
    }
    
    // Generate the previous month's days
    for ($i = 1; $i <= $first_day_of_month; $i++) {
        array_unshift($week, "");
    }
    
    // Generate the current month's days
    for ($i = 1; $i <= $days_in_month; $i++) {
        $week[] = $i;
        if (count($week) == 7) {
            $calendar[$week_number + $last_week_of_previous_month] = $week;
            $week_number++;
            $week = array();
        }
    }
    
    // Generate the next month's days
    $remaining_days = 7 - count($week);
    for ($i = 1; $i <= $remaining_days; $i++) {
        $week[] = '';
    }
    
    if (!empty($week)) {
        $calendar[$week_number + $last_week_of_previous_month] = $week;
    }
    
    return $calendar;
}

$year = 2022;
echo "<table>\n";
echo "  <tr>\n";
echo "    <th colspan='3'>$year</th>\n";
echo "  </tr>\n";

echo "  <tr>\n";
for($i=1; $i<=12; $i++){

$month_name = date('F Y', strtotime("$year-$i-01"));
$calendar = generate_calendar($i, $year);


echo "<td>\n";
echo "<table>\n";
echo "  <tr>\n";
echo "    <th colspan='8'>$month_name</th>\n";
echo "  </tr>\n";
echo "  <tr>\n";
echo "    <th>Week</th>\n";
echo "    <th>Sun</th>\n";
echo "    <th>Mon</th>\n";
echo "    <th>Tue</th>\n";
echo "    <th>Wed</th>\n";
echo "    <th>Thu</th>\n";
echo "    <th>Fri</th>\n";
echo "    <th>Sat</th>\n";
echo "  </tr>\n";
foreach ($calendar as $week_number => $week) {
    echo "  <tr>\n";
    echo "    <td>$week_number</td>\n";
    foreach ($week as $day) {
        if (empty($day)) {
            echo "    <td></td>\n";
        } else {
            echo "    <td>$day</td>\n";
        }
    }
    echo "  </tr>\n";
}
echo "</table>\n";
echo "</td>\n";

if($i==3 || $i==6 || $i==9){
echo "  </tr>\n";
echo "  <tr>\n";
}

}

echo "  </tr>\n";
echo "</table>\n";

?>

Trying to add week number which counts from first week of January (if last week of previous month is not full 7 days then first week of current month start from last week of previous month), but my code only count from first week of current month.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
wowtom16
  • 23
  • 2

2 Answers2

0

I don't believe there is any way to set the start day of the week in the standard library of PHP without manual calculation, but you can do it easily with the intl library (make sure the intl PHP extension is enabled):

$cal = IntlGregorianCalendar::createInstance();

// Set start of week to Sunday
$cal->setFirstDayOfWeek(IntlGregorianCalendar::DOW_SUNDAY);

// Get week number of the year for the current date
$weekOfYear = intval(IntlDateFormatter::formatObject($cal, 'w'));

// Advance to the next week
$cal->add(IntlGregorianCalendar::FIELD_WEEK_OF_YEAR, 1);

// ect...
Jim
  • 3,210
  • 2
  • 17
  • 23
0

I managed to get the right result (as far as I tested) with IntlCalendar and its FIELD_WEEK_OF_YEAR constant instead of counting Sundays.

I did some refactoring of your function, but ran out of time to do a full reduction of the script (there may still be lines that can be simplified/condensed).

Code: (Demo)

function generate_calendar(int $month, int $year) {
    $calendar = [];
    
    $week_number = (IntlCalendar::fromDateTime ("$year-$month-01"))->get(IntlCalendar::FIELD_WEEK_OF_YEAR);
    $month_start = new DateTime("$year-$month-01");

    // Generate the previous month's days
    if ($first_day = $month_start->format('w')) {
        $week = array_fill(1, $first_day, '');
    }

    // Generate the current month's days
    $days_in_month = $month_start->format('t');
    for ($i = 1; $i <= $days_in_month; $i++) {
        $week[] = $i;
        if (count($week) == 7) {
            $calendar[$week_number] = $week;
            $week_number++;
            $week = [];
        }
    }

    if ($week) {
        // Generate empty days for the next month
        $calendar[$week_number] = array_pad($week, 7, '');
    }
    
    return $calendar;
}
mickmackusa
  • 43,625
  • 12
  • 83
  • 136