Архив за Май 2026

Давно хотел сделать на сайте такую штуку – календарь года (текущего и каждого из прошлых), в котором с каждой даты ссылка ведёт на подборку соответствующих постов в блоге (если в тот день что-то было опубликовано) – то есть, “календарь года как в ЖЖ”. В ЖЖ такой календарь существовал и был очень удобен в качестве одного из способов поиска старых записей и/или анализа активности блога (своего или чужого). А вот, например, в WordPress такого календаря нет и, если я правильно помню, не было никогда (ну или был настолько давно, что я уже полностью забыл о его существовании) – есть только аналогичный календарь по месяцам, что совсем неудобно для большинства видов поиска и анализа.
На реализацию такой штуки своими силами нужно было некоторое количество свободного времени – и я наконец-то его нашёл! Что ещё более важно и интересно, это время я потратил не зря: сделать календарь-архив у меня получилось. Работающий пример можно посмотреть по ссылке, а в данном посте я перечислю словами все характеристики и приведу базовые PHP и CSS коды.
Характеристики моего годового календаря блога для WordPress:
– полный календарь года (видны все 12 месяцев, какая бы дата ни была на дворе на момент просмотра);
– возможность просматривать прошлые годы (но не ранее, чем год самой первой публичной записи в блоге);
– дни с публичными записями автоматически превращаются в ссылки на соответствующие даты в архиве записей;
– при наведении курсора на день ссылку всплывает подсказка с числом записей за соответствующую дату;
– в календарях за прошлые годы дата просмотра («сегодняшняя») выделяется заметной рамкой;
– у ячеек с датами, в которые была опубликована хотя бы одна запись, меняется фоновый цвет;
– у календаря – адаптивный дизайн: на больших и средних экранах показывается сетка 3×4 месяца, а на маленьких экранах месяцы года выстроены в столбик;
– запросы к базе данных оптимизированы таким образом, чтобы календарь не «тормозил» даже в блогах с десятками тысяч записей.
Ну а теперь – сами коды календаря (надеюсь, вы прочитали весь текст выше – он может вам помочь сориентироваться).
PHP-код, который можно испытывать прямо в таком виде – его легко вставить в свой макет страницы обыкновенным копипастом:

<?php
global $wpdb;


/* ======================================
   1. PRIMO ANNO DEL BLOG
====================================== */
$first_post_date = $wpdb->get_var("
SELECT post_date
FROM $wpdb->posts
WHERE post_status='publish'
AND post_type='post'
ORDER BY post_date ASC
LIMIT 1
");

$first_year = date('Y', strtotime($first_post_date));
$current_year = date('Y');
$year = isset($_GET['yr']) ? intval($_GET['yr']) : $current_year;

if ($year < $first_year) $year = $first_year;
if ($year > $current_year) $year = $current_year;


/* ======================================
   2. DATE DEI POST (QUERY SQL OTTIMIZZATA + CACHE)
====================================== */
$cache_key = 'calendar_'.$year;
$post_dates = get_transient($cache_key);
if ($post_dates === false){
	$post_dates = [];
	$results = $wpdb->get_results($wpdb->prepare("
	SELECT DATE(post_date) as post_day, COUNT(ID) as total
	FROM $wpdb->posts
	WHERE post_status='publish'
	AND post_type='post'
	AND YEAR(post_date)=%d
	GROUP BY post_day
	", $year));
	foreach ($results as $row){
		$post_dates[$row->post_day] = $row->total;
	}
	set_transient($cache_key,$post_dates,12*HOUR_IN_SECONDS);
	}


/* ======================================
   3. NAVIGAZIONE CON TUTTI GLI ANNI
====================================== */
echo '<div class="calendar-nav">';
for ($y=$first_year; $y<=$current_year; $y++){
	if ($y==$year){
		echo '<span class="current-year">'.$y.'</span>';
	}else{
		echo '<a href="?yr='.$y.'">'.$y.'</a> ';
	}
}
echo '</div>';


/* ======================================
   4. CONTROLLO "OGGI NEGLI ANNI PASSATI"
====================================== */
$today_month = date('m');
$today_day = date('d');
$today_key = $year.'-'.$today_month.'-'.$today_day;
$today_has_posts = isset($post_dates[$today_key]);


/* ======================================
   5. CONTENITORE ANNO
====================================== */
echo '<div class="calendar-year">';


/* ======================================
   6. CICLO MESI
====================================== */
for ($month=1; $month<=12; $month++) {
	echo '<div class="calendar-month-block">';
	$month_name = date_i18n('F', mktime(0,0,0,$month,1,$year));
	$month_has_posts = false;
	foreach ($post_dates as $date => $count){
		if (strpos($date,$year.'-'.sprintf('%02d',$month))===0){
			$month_has_posts = true;
			break;
		}
	}

/* titolo mese */
if ($month_has_posts){
	echo '<h3 class="month-title">
	<a href="'.get_month_link($year,$month).'">'.$month_name.'</a>
	</h3>';
	}else{
	echo '<h2 class="month-title">'.$month_name.'</h2>';
	}


/* ======================================
   7. TABELLA CALENDARIO
====================================== */
echo '<table class="calendar-month">';
echo '<thead><tr>';
$weekdays = ['L','M','M','G','V','S','D']; //da cambiare per le lingue diverse da quella italiana
foreach ($weekdays as $w){
	echo '<th>'.$w.'</th>';
	}
echo '</tr></thead>';
echo '<tbody><tr>';

/* primo giorno mese */
$first_day = date('N', strtotime("$year-$month-01"));
for ($i=1;$i<$first_day;$i++){
	echo '<td class="empty"></td>';
	}
$days = cal_days_in_month(CAL_GREGORIAN,$month,$year);
$weekday = $first_day;


/* ======================================
   8. CICLO GIORNI
====================================== */
for ($day=1;$day<=$days;$day++){
	$date = $year.'-'.sprintf('%02d',$month).'-'.sprintf('%02d',$day);
	$is_today_past = false;
	/* controllo "oggi negli anni passati" */
	if ($year < $current_year && $month==$today_month && $day==$today_day){
		$is_today_past = true;
	}
	$classes = [];
	if ($is_today_past) $classes[] = 'today-past';
	if (isset($post_dates[$date])){
		$classes[] = 'has-posts';
	} else {
		$classes[] = 'no-posts';
	}
	echo '<td class="'.implode(' ', $classes).'">';
	if (isset($post_dates[$date])){
		$count = $post_dates[$date];
		$title = ($count==1) ? '1 articolo' : $count.' articoli';
		echo '<a class="day-link" href="'.get_day_link($year,$month,$day).'" title="'.$title.'">'.$day.'</a>';
	}else{
		echo '<span class="day-number">'.$day.'</span>';
	}
	echo '</td>';
	if ($weekday==7){
		echo '</tr><tr>';
		$weekday=1;
	}else{
		$weekday++;
	}
	}

/* celle finali */
while ($weekday<=7){
	echo '<td class="empty"></td>';
	$weekday++;
	}
echo '</tr></tbody></table>';
echo '</div>';
}

echo '</div>';
?>

CSS-код визуализации календаря – скопируйте его в файл style.css вашей темы или подключите отдельно:

/* ===== navigazione anni ===== */
.calendar-nav{
	text-align:center;
	margin:40px 0;
	font-size:22px;
	line-height:2;
}
.calendar-nav a{
	margin:0 10px;
	text-decoration:none;
}
.current-year{
	font-weight:bold;
	margin:0 15px;
}
/* ===== layout mesi ===== */
.calendar-year{ display:block; }
.calendar-month-block{ margin-bottom:40px; }
/* ===== titolo mese ===== */
.month-title{
	text-align:center;
	margin-bottom:10px;
}
/* ===== tabella ===== */
.calendar-month{
	width:100%;
	border-collapse:collapse;
}
.calendar-month th{
	padding:5px;
	text-align:center;
	font-weight:bold;
}
.calendar-month td{
	padding:0;
	height:32px;
	text-align:center;
}
/* ===== giorni ===== */
.day-number{
	display:block;
	padding:6px;
}
/* celle con articoli */
.calendar-month td.has-posts{ background:#C5C5C5; }
/* link riempie tutta la cella */
.day-link{
	display:block;
	width:100%;
	height:100%;
	padding:6px;
	text-decoration:none;
	font-weight:bold;
	background:transparent; /* IMPORTANTISSIMO */
}
/* celle senza articoli */
.calendar-month td.no-posts{ background:#FFFFFF; }
/* numeri non linkati */
.day-number{
	display:block;
	padding:6px;
	background:#FFFFFF; /* garantisce bianco pieno */
}
.today-past{ outline:2px dashed #FF9800; }
/* hover */
.day-link:hover{ background:#C5C5C5; }
/* celle vuote */
.empty{ background:#FFFFFF; }
/* ===== layout desktop ===== */
@media (min-width:1024px){
.calendar-year{
	display:grid;
	grid-template-columns:repeat(3,1fr);
	gap:30px;
	align-items:start;
}
.calendar-month-block{ margin-bottom:0; }
}

В таком виде, с таким функционалом – это именно тот календарь блога, который мне был нужен. Что к нему можно или нужно добавить – даже и не знаю. Если придумаю (или кто-то подскажет) – выпущу вторую версию и о ней сообщу.


Deutsche Welle сообщает: в Берлине с утра 8 мая до вечера 9 мая вблизи воинских мемориалов постановление полиции запрещает использование советской и российской символики. Под запрет попадут советская и российская военная форма и знаки различия, георгиевские ленты, флаги СССР, России, Беларуси, Чечни и портреты их руководителей, а также изображения Украины «без учета оккупированных территорий». Кроме того, будет запрещено исполнение советских и российских военных маршей.
Может даже показаться странным, что кто-то решил упустить такую возможность устроить ежегодную перепись идиотов и кандидатов на вылет (в буквальном смысле слова) из Германии. Но на самом деле на пятый год войны в Украине авторы берлинского запрета всех этих персонажей уже знают. А нам 8 и 9 мая интернет покажет самых упоротых – тех, кто запет каким-то образом попробует проигнорировать. Надеюсь, кто-нибудь из журналистов догадается сделать репортаж об этой части мира животных: интересно же, что происходит за пределами того пузыря, в котором живут имеющие человеческий мозг люди.


404 Media сообщает: строительный бум дата-центров для нужд искусственного интеллекта спровоцировал резкий рост цен и нехватку не только оперативной памяти, но и жёстких дисков, а это угрожает работе крупнейших цифровых архивных проектов: например, Internet Archive (сервис Wayback Machine) и фонда Викимедиа.
Сервисами Викимедии я не особенно част пользуюсь, а вот Wayback Machine – гениальный, интересный и полезный мне проект, захожу туда если не каждую неделю, то несколько раз в месяц точно. Только благодаря этому проекту из интернета хоть что-то со временем не пропадает навсегда (вопреки очень распространённому мифу, интернет «всё помнит» гораздо хуже книг и рукописей). И мне было бы очень жаль, если бы его архивы перестали обновляться или даже начали теряться из-за нехватки новых дисков.
А потому у меня в голове родился черновик проекта, над которым я бы даже сам мог подробно подумать, но который вряд ли в ближайшее время смогу реализовать сам: создать скрипт периодического архивирования сайта, встраиваемый в движок самого сайта. Что-то вроде динамично пополняющегося музея сайта, который будет храниться на уже существующем сервере того же самого сайта. Порции архива можно, по запросу, пересылать в Internet Archive, когда тот добывает очередную порцию новых жёстких дисков.
Надеюсь, что кто-нибудь способный разовьёт эту мысль быстрее и лучше меня.


Пишут, что Сбер и Т-Банк (бывший Тинькофф) отключили в своих приложениях чаты с другими пользователями и комментарии к переводам. Это нововведение логично связывают с тем, что вследствие «замедления» и фактической полной блокировки телеграма в РФ люди начали переписываться во всяких других чатах, приложениях и просто комментариях.
Предположение, конечно, интересное, но я бы ни за что не додумался переписываться в приложении Сбера: среди населения распространено оно, как я предполагаю, не меньше телеги, но его вероятная читаемость «органами» может быть ещё выше, чем у той же телеги. Так что если баковские чаты и отключили по требованию «сверху», то именно в связи с нехваткой технических средств для создания системы контроля.
Пока я пытаюсь осознать техническую сторону вышеизложенного феномена, люди пусть продолжают искать способы переписки.
Да они и без меня ищут – общаться-то как-то нужно. А сильно заинтересованные люди всегда найдут.


Фильм «Бугония»

Вообще-то я не собирался смотреть фильм «Бугония» («Bugonia», режиссёр Йоргос Лантимос, 2025 год), так как в его официальном описании ничего меня особенно не «зацепило». Но потом мне совершенно случайно попалось на глаза несколько умеренно положительных отзывов, и я всё-таки решился. Как оказалось – совсем не зря.
В общем, «Бугония» – это такая психическо-фантастическая трагикомедия (нет, я не ошибся ни в одном слове), которая развивается по интересному сценарию и остаётся хорошим фильмом даже после того, как приходит к наименее оригинальному из возможных финалов. Да, звучит странно, ощущения после просмотра – тоже странные, но фильм – скорее хороший, чем плохой. А странными ощущения я называю потому, что режиссёр как бы обманывает зрителя: весь фильм показывает нам психологическое противостояние психа-маньяка и его заложницы, а в последних двух сценах перепрыгивает в полную противоположность всего показанного – да ещё и даёт этой противоположности несколько комическую окраску. Если это – способ подшутить над зрителем, то я ничего против не имею, просто предпочитаю гораздо более тонкий юмор.
К счастью, качественных смешных и грустных моментов хватает в основной части фильма, так что его спокойно можно смотреть и смотреть целиком. Обычно хотя бы частичный пересказ сюжета кажется мне глупым занятием, так что обозначу совсем коротко, что именно вы увидите. Упаковщик посылок и пчеловод-любитель живёт в деревенском доме на опушке леса, из близких людей у него – только давно лежащая в коме мать и кузен с явными особенностями в развитии. Упаковщик когда-то был очень привязан к маме, а сейчас обеспокоен ещё и вымиранием пчёл и, возможно, даже человечества. Поэтому он разработал идеальный план спасения: нужно провести личные переговоры с Императором пришельцев из галактики Андромеды и потребовать, чтобы те прекратили производить на Земле эксперименты над людьми и над пчёлами. Упаковщик точно знает, как выглядит внутри и снаружи космический корабль пришельцев, а так же – что ещё более важно – по каким небольшим внешним признакам распознать внедрившихся на Землю агентов пришельцев. Попасть к Императору можно с помощью захваченного в плен агента-инопланетянина – логично же! Ну, он, упаковщик, и захватывает – главу той самой корпорации, в которой сам работает, всемирно известную менеджерку и сторонницу новой корпоративной организации. А дальше зрителю остаётся наблюдать, как упаковщик пытается убедить свою работодательницу взять себя на инопланетянский космический корабль и что из этого выходит.
Снято всё это действительно хорошо и нескучно: в этом есть заслуга не только сценаристов и режиссёра, но и актёров, сыгравших психа-похитителя и его жертву очень правдоподобно – на это стоило бы посмотреть даже полностью независимо от сюжета фильма. Но сюжет есть, и он – не чистая драма и не ужастик, а именно психический, безумный и потому – ещё и смешной (в хорошем смысле слова) для стороннего наблюдателя.
Так что не буду тратить ваше время на чтение текстовой воды, а просто посоветую фильм посмотреть (если вы по каким-то причинам этого ещё не сделали).

Есть в фильме и одна эстетическая нелогичность, но я никак не могу написать о ней без фатального спойлерства. Так что внимательно смотрите сами.


N.B.: давние читатели могли заметить, что я не смотрю фильмы некоторых жанров (анимация, фэнтези, боевики, лёгкие комедии, мюзиклы) и почти не смотрю сериалы. Если же вам интересны такие фильмы (или вы просто хотите узнать, откуда я узнаю о некоторых интересных фильмах) – можете поискать идеи для просмотра в кинорецензиях Алекса Экслера.


Иногда я использую воскресную видео-рубрику для того, чтобы сохранить на память какой-нибудь прикол. Или какой-нибудь бред, вроде вот этого:

Интересно, а сколько дрончиков собрали москвичи в гаражах и на дачах с целью отправить на фронт? Надеюсь, ничтожно мало. Точнее, знаю.


Музыка без зет

А в моём концертном зале без буквы зет – снова человеческая музыка.
В этот раз – группа ДДТ со свежим клипом на песню «Костёр»:

А будущее нашего мира пока ближе к клипу, чем к песне.


Я сам ничего такого не заметил (возможно, потому что я не полностью соответствую понятию «западная аудитория»), но вроде бы кремлёвская бот-сеть «Матрёшка» активно распространяет в социальных сетях на западную аудиторию дезинформацию о том, что за покушением на Дональда Трампа стоит Украина. Ничего нелогичного в попытке создания подобного фейка нет – он основывается на примерно всем известном факте действительно не очень хороших отношений Украины с нынешним американским руководством.
Ну, ладно: в случае чего, смогу аргументированно ответить какой-нибудь европейской жертве матрёшечной пропаганды.


Странные же иногда случаются смешения киножанров: например, производственная драма с элементами бытовухи и чёрно-юморная комедия в одном фильме. Только что обнаруженный мною конкретный пример – короткометражка «Холодно» (режиссёр Данил Иванов, 2021 год).

И мне это скорее понравилось – потому что не попсово.


Один хороший человек недавно прислал ссылку на партию аудио-файлов, которых недоставало в моём архиве исторических передач «Эха Москвы». И вот у меня дошли руки систематизировать этот ценнейший подарок: удалить несколько повторов, привести названия файлов к моему «архивному» стандарту и залить всё на сервер вместе с обновлённым xml-файлом.
И вот теперь я могу официально объявить, что и архив эховской передачи «Цена революции» выложен у меня на сайте почти полностью!
Так что если вы – любитель той передачи и уже давно ожидали вышеуказанного обновления, заходите и слушайте с новой силой.
Правда, приславший недостающие файлы человек был уверен, что высылает мне записи передачи «Цена победы», но и во времена выхода двух передач на радио иногда происходила некоторая организационная путаница, так что не стоит предъявлять какие-то претензии…
А если у вас сохранились архивные файлы, пригодные для публикации – можете и поделиться ими со мной…