Бинарный календарь
Нет пока желания делать Excel'евский "календарь батрака", а вот какой-нибудь интересный вид календаря замутить можно. Ну и в качестве новогодней ёлочки пойдёт.
12 столбцов - это месяцы, дни отсчитываются вниз как двоичные числа, сдвигом всей "ёлочки" вниз учитывается день недели для первого числа месяца (Пн=0, ..., Вс=6 позиций сдвига). Красный цвет - выходные, зелёный - неродные рабочие, золотой - текущий день (нужно точное совпадение дня, месяца и года).
Так как больше 31 дня в месяце не бывает, достаточно пяти клеточек-"бит" для вывода одного числа месяца.
Всё записано в одном методе drawBinaryCalendar, правда, переносы
выходных всё равно каждый год будут разные, они учтены в массивах exr, exw.
Ниже приведён скрипт в работе и его исходный код.
Это кучка разделов, а не графическая канва или таблица. При желании, наверное, календарик легко расширить :)
<style>
.table {
display: table;
padding: 0;
border: 0;
text-align: center;
margin: 0 auto;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
}
.c0, .c1, .c2, .c3 {
width: 10px;
height: 10px;
margin:1px 0;
}
.c0 {
background-color: transparent;
}
.c1 {
background-color: #f00;
}
.c2 {
background-color: #080;
}
.c3 {
background-color: #fd0;
}
</style>
<div id="binaryCalendar">Включите Javascript в браузере для работы приложения</div>
<script>
function drawBinaryCalendar (y) { //Бинарный календарь на год y
let hd = [ //Праздники, месяцы нумеруем с единицы! Сб и Вс "красные" автоматически
[1,1], [2,1], [3,1], [4,1], [5,1], [6,1], [7,1], [8,1],
[23,2],
[8,3],
[1,5], [9,5],
[12,6],
[4,11]
];
let exr = [ //Исключения (переносы выходного) для 2022 - эти дни станут выходными
[7,3], [3,5], [10,5]
];
let exw = [ //Исключения (переносы выходного) для 2022 - эти дни станут рабочими
[5,3]
]
function includesArray (arr, val) { //Есть ли массив val в массиве массивов arr
arr = JSON.stringify(arr);
val = JSON.stringify(val);
return arr.indexOf(val) != -1;
}
function isRestDay (d) { //d - дата выходного?
let dm = [];
dm.push (d.getDate(),d.getMonth()+1);
switch (d.getDay()) {
case 0: case 6:
isRest = true;
break; //субботы и воскресенья - выходные
default:
isRest = false;
if (includesArray(hd,dm)) isRest = true; //постоянные праздники
break;
}
if (includesArray(exr,dm)) isRest = true;
else if (includesArray(exw,dm)) isRest = false;
return isRest;
}
let days_in_month=[31,28,31,30,31,30,31,31,30,31,30,31]; //дней в месяцах
if ((y%4==0&&y%100!=0)||(y%400==0)) {days_in_month[1]=29;} //високосный год
let a = Array(73).fill(0).map(() => {return Array(37).fill(0)});
//73 столбца (12 мес. по 5 позиций на число + 13 разделителей, 37 строк (31 день + сдвиг вниз до 6 дней)
//Вычисление кодов классов:
let td = new Date(), tdd = td.getDate(), tdm = td.getMonth(), tdy = td.getFullYear();
for (let m=0; m<12; m++) { //перебираем месяцы
let w = (new Date(y, m, 1)).getDay(); //Первый день месяца для сдвига, 0 = Вс
if (w == 0) w = 6; else w--; //Сдвиг 0 = Пн
let k = 1; //счётчик дней в месяце
for (let i=w; i<w+days_in_month[m]; i++) {
let d = new Date(y, m, k); //текущая дата в календаре
let c= isRestDay(d) ? 1 : 2; //номер класса: 0 - пусто, 1 - красный, 2 - зелёный, 3 - жёлтый
if (d.getDate() == tdd && d.getMonth() == tdm && y == tdy) c = 3; //сегодня
let p2 = 1; //степень двойки
for (let b=0; b < 6; b++) {
a[m*6 + (5-b)][i] = (k & p2) ? c : 0;
p2 <<= 1;
}
k++;
}
}
//Отрисовка:
let txt = '<div class="table">';
for (i=0;i<37;i++) {
txt += '<div class="row">';
for (j=0;j<73;j++) {
txt += '<div class="cell c'+a[j][i]+'"></div>';
}
txt += '</div>'+"\n";
}
txt += '</div>'+"\n";
document.getElementById('binaryCalendar').innerHTML = txt;
}
drawBinaryCalendar (2022); //вызвать метод
</script>
Идея такого календаря взята отсюда
UPD. Впрочем, чтобы не делать потом отдельной заметки, прикрепим и обычный تقویم کارگر مزرعه на этой же странице, название на фарси означает всё то же самое :)
У нас пока что остаются следующие постоянные праздники (привожу официальные названия):
- 1, 2, 3, 4, 5, 6 и 8 января — Новогодние каникулы;
- 7 января — Рождество Христово;
- 23 февраля — День защитника Отечества;
- 8 марта — Международный женский день;
- 1 мая — Праздник Весны и Труда;
- 9 мая — День Победы;
- 12 июня — День России;
- 4 ноября — День народного единства.
Переносятся в 2022 году следующие дни:
- с субботы 1 января на вторник 3 мая;
- с воскресенья 2 января на вторник 10 мая;
- с субботы 5 марта на понедельник 7 марта.
То есть, "чёрной субботой" станет только 5 марта.
Скачать календарь на 2022 год, один лист A4, файл Excel 2007 и выше в архиве .zip (11 Кб)
UPD (2). Аналогичный бинарный календарь на 2023-й год, код немного упрощён (все красные дни в одном списке), стиль с клетками, нет выделения сегодня (строка 84, см. исходник страницы).
UPD (3). Аналогичный бинарный календарь на 2024-й год, из-за трёх рабочих суббот пришлось вернуть список исключений (переносов выходных) exw.
Бинарный календарь-2025 (4 Кб)
Бинарный календарь-2026, HTML (4 Кб)
Бинарный календарь-2027, HTML (4 Кб)
05.11.2021, 22:15 [1456 просмотров]

