A calendar written with IntlCalendar class

Code
<?php

// Berlin - Germany
$c IntlCalendar::createInstance('Europe/Berlin''de_DE');
$renderer = new CalendarMonthRenderer(new IntlDateFormatter('de_DE'nullnull));
echo 
$renderer->render(new CalendarMonth($c));

// USA - New York
$c IntlCalendar::createInstance('America/New_York''en_US');
$renderer = new CalendarMonthRenderer(new IntlDateFormatter('en_US'nullnull));
echo 
$renderer->render(new CalendarMonth($c));


/**
 * This code snippet is no copy and paste example. It has no error
 * handling and isn't generic or clean written enough to be used in 
 * production.
 */
class CalendarMonth
{
    private 
$calendar;
    private 
$now;
    
    const 
DAY IntlCalendar::FIELD_DATE;
    const 
MONTH IntlCalendar::FIELD_MONTH;
    const 
DOW_LOCAL IntlCalendar::FIELD_DOW_LOCAL;
    
    public function 
__construct(IntlCalendar $calendar)
    {
        
$this->calendar $calendar;
        
$this->now $calendar->getTime();
    }
    
    public function 
getNow()
    {
        return 
$this->now;
    }
    
    public function 
createStructure()
    {
        
$calendar $this->calendar;
        
        
// beginning of the week
        
$calendar->set(self::DAY$calendar->getMinimum(self::DAY));
        
$dayOfWeek $calendar->get(self::DOW_LOCAL);
        
$month $calendar->get(self::MONTH);
        
$calendar->add(self::DAY, -($dayOfWeek 1));

        
$structure = [];
        
$week = [];
        while (
$calendar->get(self::MONTH) <= $month || 
            !
$this->isNewWeek($calendar)
        ) {
            if (
$this->isNewWeek($calendar)) {
                
$week = [];
            }
            
            
$week[] = $calendar->getTime();
            
            if (
$this->isEndOfWeek($calendar)) {
                
$structure[] = $week;
                if (
$calendar->get(self::MONTH) != $month) {
                    break;
                }
            }
            
            
$calendar->add(self::DAY1);
        }
        
        return 
$structure;
    }
    
    private function 
isNewWeek(IntlCalendar $c)
    {
        return 
=== $c->get(self::DOW_LOCAL);
    }
    
    private function 
isEndOfWeek(IntlCalendar $c)
    {
        return 
=== $c->get(self::DOW_LOCAL);
    }
}

class 
CalendarMonthRenderer
{
    private 
$formatter;
    
    public function 
__construct(IntlDateFormatter $formatter)
    {
        
$this->formatter $formatter;
    }
    
    public function 
render(CalendarMonth $calendar)
    {
        
$days $weekdays '';
        foreach (
$calendar->createStructure() as $pos => $week) {
            
$days .= '<tr>';
            foreach(
$week as $day) {
                if (
=== $pos) {
                    
$weekdays .= '<td>' $this->format($day 1000'E') . '</td>';
                }
            
                
$days .= '<td align="right">' $this->format($day 1000'd') . '</td>';
            }
            
$days .= '</tr>';
        }
        
        
$caption '<caption>' $this->format($calendar->getNow() / 1000'LLLL') . '</caption>';
        
        return 
'<table border="1">' $caption '<tr>' $weekdays '</tr>' $days '</table>';
    }
    
    private function 
format($c$format)
    {
        
$this->formatter->setPattern($format);
        return 
$this->formatter->format($c);
    }
}
Result
Februar
Mo.Di.Mi.Do.Fr.Sa.So.
303112345
6789101112
13141516171819
20212223242526
272812345
February
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
2627281234
Used Versions
PHP 8.2, Laminas MVC 3.2, Symfony 5.2, Laravel 8.28, PHPUnit 9.5, Doctrine ORM 2.8