30 февраля или логичный календарь :)
Мне нравятся реформаторы календаря. Наряду с толкованием Апокалипсиса и верой в злокозненных пришельцев (православный вариант - бесов, либеральный - агентов спецслужб), стремление реформировать календарь - третий верный индикатор той весёлой шизофрении, что делает жизнь в обывательском болоте приемлемой (в СССР повышенная креативность отчего-то именовалась вялотекущей шизофренией).
Так вот, как раз намедни был разговор на тему с одним чудаком. Почему из нескольких возможных вариантов распределения количества дней по месяцам мы выбрали явно не самый удачный - 7 месяцев по 31 дню, 4 - по 30 и один - 28 или 29.
По-моему, в блоге соответствующее диофантово уравнение уже решалось. Наш обычный год - пятое решение в списке, а его "логичный" - второе. Мне лично симпатичен и девятый вариант с 12 "лунными" месяцами по 28 дней и 13-м из 29 дней.
Правда, нарисовать такой год изменённым скриптом календаря не получится, потому что вывод скрипта зависит от результата, возвращаемого функцией date('w')
.
Быстрее будет реализовать на PHP банальную формулу Зеллера и написать соответствующее обрамление. Для простоты - без класса и всегда с выводом "вертикального" календаря на текущий год из 3 строк и 4 столбцов.
Предполагается, что год всегда начинается с 1 января и состоит из 12 месяцев (отчего-то, количество месяцев никогда не пытаются "оптимизировать", хотя по мне, хватило бы семи :) Также есть некий месяц, куда добавляется дополнительный день по правилам григорианского календаря. Ведь последний довольно точен, а погрешность в сутки, которую он накопит примерно за 10000 лет, легко предотвращается секундами координации, используемыми уже 45 лет.
В общем, представьте - в январе всегда 31 день, в феврале - 30, в марте - снова 31 и так до ноября, в котором будет 31. Скучный декабрь в ожидании Нового года имеет 29 дней в обычный год и 30 в високосный.
Изменив массив $dayscount
и переменную $leapmonth
в функции draw
можно попробовать и другие варианты 12-месячного года, а "безумный календарь" на текущий год будет выглядеть в браузере вот так:
"логичный календарь"-2016
Ну и полный исходник шыдевра, конечно (на момент написания и без обрамляющих тегов HTML):
<?php function getweekday($d,$m,$year) { //день недели по формуле Зеллера для даты ДД.ММ.ГГГГ if ($m<3) { $m+=12; $year--; } $c=floor($year/100); $y=$year%100; $wd=($d+floor(13*($m+1)/5)+$y+floor($y/4)+floor($c/4)-2*$c)%7; //0..6=Сб..Пт if ($wd<2) $wd+=6; else $wd--; //1..7=Пн..Вс return $wd; } function leapyear ($y) { //true, если год високосный return ($y%4==0) and ($y%100!=0) or ($y%400==0); } function daycolor ($d,$m,$year,$wd) { //red - выходной или праздник, иначе black //праздники - только ДД.ММ, переносы выходных не учитываются $holidays = array ( array (1,1), array (7,1), array (23,2), array (8,3), array (1,5), array (9,5), array (12,6), array (4,11) ); if ($wd>5) return 'red'; for ($i=0; $i<count($holidays); $i++) if ($d==$holidays[$i][0] and $m==$holidays[$i][1]) return 'red'; return 'black'; } function draw($year) { //вывод календаря на год $year $months=array("Январь","Февраль","Март","Апрель","Май","Июнь", "Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"); //Названия месяцев $days=array("Пн","Вт","Ср","Чт","Пт","Сб","Вс"); //Названия дней недели $dayscount=array("31","30","31","30","31","30", "31","30","31","30","31","29"); //Число дней в месяцах $leapmonth=12; //Номер "високосного" месяца, к которому добавляется 366-й день $text = '<div align="center"><b>'.$year.'</b></div>'."\n"; $text .= '<table align="center" border="0" cellpadding="6" cellspacing="0">'."\n"; $wd = getweekday(1,1,$year); for ($r=1; $r<=3; $r++) { $text .= '<tr>'."\n"; for ($c=1; $c<=4; $c++) { $text .= '<td>'."\n"; $m = ($r-1)*4+$c; $text .= '<div align="center">'.$months[$m-1].'</div>'."\n"; $d=1; $upd = $dayscount[$m-1]; if (leapyear($year) and $m==$leapmonth) $upd++; $text .= '<table align="center" border="0" cellpadding="3" cellspacing="0">'."\n"; $cal = array (); for ($rr=1; $rr<=7; $rr++) $cal[$rr] = array (2=>' ',3=>' ',4=>' ',5=>' ',6=>' ',7=>' '); for ($cc=2; $cc<=7; $cc++) { for ($rr=1; $rr<=7; $rr++) { if ($cc==2 and $rr!=$wd) continue; else if ($d<=$upd) { $color = daycolor ($d,$m,$year,$wd); $cal[$rr][$cc] = '<font color="'.$color.'">'.($d++).'</font>'; $wd++; if ($wd>7) $wd=1; } } } for ($rr=1; $rr<=7; $rr++) { $text .= '<tr>'."\n"; for ($cc=1; $cc<=7; $cc++) { $text .= '<td width="15%" align="right" nowrap>'."\n"; if ($cc==1) $text .= ($rr<6?'':'<font color="red">').$days[$rr-1].($rr<6?'':'</font>')."\n"; else $text .= $cal[$rr][$cc]."\n"; $text .= '</td>'."\n"; } $text .= '</tr>'."\n"; } $text .= '</table>'."\n"; $text .= '</td>'."\n"; } $text .= '</tr>'."\n"; } $text .= '</table>'."\n"; return $text; } echo draw (date("Y")); //вызов для текущего года ?>
Список праздников, которые всегда красные, задаётся в функции daycolor
. Можно впечатать "сумасшедший календарь" на плакат и разыграть подарком невнимательного знакомого.
20.02.2016, 22:57 [7316 просмотров]