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
April
Mo.Di.Mi.Do.Fr.Sa.So.
2930311234
567891011
12131415161718
19202122232425
262728293012
April
SunMonTueWedThuFriSat
28293031123
45678910
11121314151617
18192021222324
2526272829301
Used Versions
PHP 8.0, Laminas MVC 3.2, Symfony 5.2, Laravel 8.28, PHPUnit 9.5, Doctrine ORM 2.8