[Сценарий] Функция Рабочий/Выходной день

Не требует установки программ или изменения файлов

Модераторы: immortal, newz20

Аватара пользователя
xor
Сообщения: 2038
Зарегистрирован: Сб ноя 22, 2014 8:45 pm
Благодарил (а): 284 раза
Поблагодарили: 629 раз

[Сценарий] Функция Рабочий/Выходной день

Сообщение xor » Вт сен 06, 2016 1:45 am

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

Добавил функцию isHolyday(), которая учитывает это дело на основе производственного календаря.
Область определения 2016-2019 гг. РФ
Календарь в таблицеПоказать

Код: Выделить всё

//производственный календарь 2016 России
//с сайта http://data.gov.ru/opendata/7708660670-proizvcalendar
//выходные дни по-месячно, рабочие короткие помечены *
//грузим в таблицу pr_calendar

//Создаём сценарий и выполняем его  один раз
SQLExec("create table IF NOT EXISTS pr_calendar  ( n_year int(4) NOT NULL, n_month int(2) NOT NULL, holidays varchar(150) NOT NULL);");
//
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,1,'1,2,3,4,5,6,7,8,9,10,16,17,23,24,30,31')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,2,'6,7,13,14,20*,21,22,23,27,28')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,3,'5,6,7,8,12,13,19,20,26,27')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,4,'2,3,9,10,16,17,23,24,30')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,5,'1,2,3,7,8,9,14,15,21,22,28,29')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,6,'4,5,11,12,13,18,19,25,26')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,7,'2,3,9,10,16,17,23,24,30,31')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,8,'6,7,13,14,20,21,27,28')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,9,'3,4,10,11,17,18,24,25')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,10,'1,2,8,9,15,16,22,23,29,30')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,11,'3*,4,5,6,12,13,19,20,26,27')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2016,12,'3,4,10,11,17,18,24,25,31')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,1,'1,2,3,4,5,6,7,8,9,10,11,14,15,21,22,28,29')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,2,'4,5,11,12,18,19,22*,23,25,26')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,3,'4,5,7*,8,11,12,18,19,25,26')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,4,'1,2,8,9,15,16,22,23,29,30')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,5,'1,6*,7,8,9,13,14,20,21,27,28')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,6,'3,4,10,11,12*,17,18,24,25')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,7,'1,2,8,9,15,16,22,23,29,30')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,8,'5,6,12,13,19,20,26,27')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,9,'2,3,9,10,16,17,23,24,30')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,10,'1,7,8,14,15,21,22,28,29')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,11,'3*,4,5,6,11,12,18,19,25,26')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2017,12,'2,3,9,10,16,17,23,24,30,31')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,1,'1,2,3,4,5,6,7,8,9,10,13,14,20,21,27,28')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,2,'3,4,10,11,17,18,22*,23,24,25')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,3,'3,4,7*,8,10,11,17,18,24,25,31')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,4,'1,7,8,14,15,21,22,28,29,30*')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,5,'1,5,6,8*,9,12,13,19,20,26,27')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,6,'2,3,9,10,11*,12,16,17,23,24,30')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,7,'1,7,8,14,15,21,22,28,29')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,8,'4,5,11,12,18,19,25,26')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,9,'1,2,8,9,15,16,22,23,29,30')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,10,'6,7,13,14,20,21,27,28')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,11,'3,4,5,10,11,17,18,24,25')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2018,12,'1,2,8,9,15,16,22,23,29,30,31*')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,1,'1,2,3,4,5,6,7,8,9,10,12,13,19,20,26,27')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,2,'2,3,9,10,16,17,22*,23,24,25')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,3,'2,3,7*,8,9,10,16,17,23,24,30,31')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,4,'6,7,13,14,20,21,27,28,30*')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,5,'1,4,5,8*,9,11,12,18,19,25,26')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,6,'1,2,8,9,11*,12,15,16,22,23,29,30')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,7,'6,7,13,14,20,21,27,28')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,8,'3,4,10,11,17,18,24,25,31')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,9,'1,7,8,14,15,21,22,28,29')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,10,'5,6,12,13,19,20,26,27')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,11,'2,3,4,9,10,16,17,23,24,30')");
SQLExec("insert into pr_calendar (n_year,n_month,holidays) values (2019,12,'1,7,8,14,15,21,22,28,29,31*')");


Далее пишем функцию

Код: Выделить всё

//определяет, является ли день нерабочим = 1 или нет = 0
//На основе производственного календаря
//Чтобы дополнить isWeekEnd(),isWeekDay()
//isHoliday(mktime(0,0,0,1,1,2016)) or isHoliday()
// @return int
function isHoliday($dt = null){
    if (!isset($dt)) $dt = time();
        $resp = 0;
    $ye = date('Y',$dt); // год
    $mn = date('n',$dt); // месяц 1-12
    $d  = date('j',$dt);  // число
    
    $Record = SQLSelectOne("Select holidays from pr_calendar where n_year=".$ye." and n_month=".$mn);
    
      $clnd=','.$Record['holidays'].','; // добавим запятых в начало и конец для единообразия
       $pos = strpos($clnd,','.$d.',');  //есть ли нужный нам день месяца в числах выходных?
       
           if($pos === false){ //нет, не выходной((
         $pos = strpos($clnd,','.$d.'*,');  //а, может, суббота или воскресенье стали коротким рабочим днём?
         if($pos>0) {
           $resp = 0; //увы, рабочий, хоть и короткий
         }
       }else{
         $resp = 1; //да, выходной!
       }
    return $resp ;
} 
Функцию можно использовать вместо isWeekEnd(),isWeekDay().
Для рабочих дней 0, для нерабочих 1.

Код: Выделить всё

isHoliday(mktime(0,0,0,1,1,2016))  //Праздник ли  1 января? 
Result: 1                                        //Да

isHoliday()  //Праздник ли сегодня?
Result: 0    //Нет
За это сообщение автора xor поблагодарили (всего 4):
directman66 (Ср янв 31, 2018 3:23 pm) • Ron (Чт фев 01, 2018 2:03 pm) • slgeo (Пн май 14, 2018 4:47 pm) • olegvolk75 (Чт июн 07, 2018 1:45 pm)
Рейтинг: 4.65%
Аватара пользователя
sorochan.ilya
Сообщения: 22
Зарегистрирован: Вс янв 24, 2016 11:20 am
Благодарил (а): 22 раза
Поблагодарили: 10 раз

Re: Функция Рабочий/Выходной день

Сообщение sorochan.ilya » Вт сен 06, 2016 11:47 am

Интересная идея! По этой сылке: http://xmlcalendar.ru/data/ru/2016/calendar.xml XML файл с производственным календарем на 2016 год, соответственно после публикации на 2017 год ссылка будет http://xmlcalendar.ru/data/ru/2017/calendar.xml, может может кто к алисе прикрутить как приложение, чтобы сама обновляла свои знания о том какой сегодня день.
Ivan
Сообщения: 1473
Зарегистрирован: Сб окт 12, 2013 11:03 pm
Благодарил (а): 49 раз
Поблагодарили: 327 раз

Re: Функция Рабочий/Выходной день

Сообщение Ivan » Вт сен 06, 2016 11:52 am

Можно поставить модуль Google Calendar Sync. Добавить к своим календарям нужный "Праздники РФ" "Прадники ..." и сделать импорт. От обычных дат отличаются группой

Отправлено с моего SM-G7102 через Tapatalk
За это сообщение автора Ivan поблагодарил:
viktor6 (Чт май 09, 2019 11:37 am)
Рейтинг: 1.16%
Linux, Raspberry PI, MySensors
Connect: http://connect.smartliving.ru/profile/53
Мои проекты: http://smartliving.ru/profile/4
Аватара пользователя
sorochan.ilya
Сообщения: 22
Зарегистрирован: Вс янв 24, 2016 11:20 am
Благодарил (а): 22 раза
Поблагодарили: 10 раз

Re: Функция Рабочий/Выходной день

Сообщение sorochan.ilya » Вт сен 06, 2016 12:04 pm

А те выходные которые переносят каждый год по разному, например в этом году:
Постановлением Правительства РФ от 24.09.2015 "О переносе выходных дней в 2016 году" утвержден порядок переноса:
с субботы 2 января на вторник 3 мая;
с воскресенья 3 января на понедельник 7 марта;
с субботы 20 февраля на понедельник 22 февраля.
Ivan
Сообщения: 1473
Зарегистрирован: Сб окт 12, 2013 11:03 pm
Благодарил (а): 49 раз
Поблагодарили: 327 раз

Re: Функция Рабочий/Выходной день

Сообщение Ivan » Вт сен 06, 2016 12:49 pm

Если вопрос ко мне. То там куча календарей. Выбирайте тот который вам подходит. Есть и официальный. Есть сами делают. Вы можете скопировать и поправть в свой

Отправлено с моего SM-G7102 через Tapatalk
Linux, Raspberry PI, MySensors
Connect: http://connect.smartliving.ru/profile/53
Мои проекты: http://smartliving.ru/profile/4
Аватара пользователя
xor
Сообщения: 2038
Зарегистрирован: Сб ноя 22, 2014 8:45 pm
Благодарил (а): 284 раза
Поблагодарили: 629 раз

Re: Функция Рабочий/Выходной день

Сообщение xor » Вт сен 06, 2016 2:35 pm

Интересно ещё реагировать на какие- нибудь события в календаре, например, "Отпуск", чтобы тоже будильник не срабатывал!

Отправлено с моего Nexus 5 через Tapatalk
Dark_Veter
Сообщения: 295
Зарегистрирован: Вт апр 23, 2013 5:16 pm
Откуда: Брянск
Благодарил (а): 18 раз
Поблагодарили: 94 раза

Re: Функция Рабочий/Выходной день

Сообщение Dark_Veter » Вт сен 06, 2016 4:13 pm

sorochan.ilya писал(а):Интересная идея! По этой сылке: http://xmlcalendar.ru/data/ru/2016/calendar.xml XML файл с производственным календарем на 2016 год, соответственно после публикации на 2017 год ссылка будет http://xmlcalendar.ru/data/ru/2017/calendar.xml, может может кто к алисе прикрутить как приложение, чтобы сама обновляла свои знания о том какой сегодня день.
Вот, давно писал уже, не много костыльно, но вроде работает:

Код: Выделить всё

function weekDay($date) {
    $this_year = (int) date('Y', $date);
    //Загружаем производственный календарь
    $productionCalendar = @file_get_contents('http://xmlcalendar.ru/data/ru/' . $this_year . '/calendar.xml');
    if ($productionCalendar) { //Если прочитали без ошибок
        sg('DateTime.productionCalendar', $productionCalendar); //Запишем на всякий случай))
    } else { //Если не прочиталось
        $productionCalendar = gg('DateTime.productionCalendar'); // Возьмем ранее загруженный календарь
    }

    //Проверяем сегодняшний день по производственному календарю (рабочий или нет)
    $weekDay = -1;
    $this_date = date('m.d', $date);
    $calend = new SimpleXMLElement($productionCalendar);
    foreach ($calend->days->day as $day) {
        $type = $day->attributes()->t; //тип дня: 1 - выходной день, 2 - короткий день, 3 - рабочий день (суббота/воскресен)
        $CalDate = $day->attributes()->d; //дата
        if ($this_date == $CalDate) {
            if ($type == 1) { //выходной
                $weekDay = 0;
            } elseif ($type == 2) {
                //Короткий день
                //$weekDay = 1;
            } elseif ($type == 3) { //Перенесенный рабочий
                $weekDay = 0;
            }
        }
    }
    //Если в производственном календаре ничего не нашлось
    if ($weekDay == -1) {
        if (date('w', $date) == 0 || date('w', $date) == 6) {
            $weekDay = 0;
        } else {
            $weekDay = 1;
        }
    }
    return $weekDay;
} 
В 00 часов обновляется и записывает в свойство. В коннексе у меня можно посмотреть.
За это сообщение автора Dark_Veter поблагодарил:
olegvolk75 (Чт июн 07, 2018 1:47 pm)
Рейтинг: 1.16%
Debian GNU/Linux 7.9 (wheezy), версия 0.9.0b, Connect
Аватара пользователя
xor
Сообщения: 2038
Зарегистрирован: Сб ноя 22, 2014 8:45 pm
Благодарил (а): 284 раза
Поблагодарили: 629 раз

Re: Функция Рабочий/Выходной день

Сообщение xor » Вт сен 06, 2016 6:17 pm

Я после Яндекса с его погодой косо смотрю на сетевые источники. Сегодня он есть, а завтра...
Из-за этого и полез на data.gov.ru.
Не в курсе, xmlcalendar.ru - у него статус какой?

Отправлено с моего Nexus 5 через Tapatalk
Аватара пользователя
sorochan.ilya
Сообщения: 22
Зарегистрирован: Вс янв 24, 2016 11:20 am
Благодарил (а): 22 раза
Поблагодарили: 10 раз

Re: Функция Рабочий/Выходной день

Сообщение sorochan.ilya » Чт сен 08, 2016 9:56 am

Про статус xmlcalendar.ru - незнаю :(, но вроде давно уже работает. Dark_Veter, спасибо за код, работает.
Аватара пользователя
webms
Сообщения: 498
Зарегистрирован: Чт дек 15, 2016 3:13 am
Благодарил (а): 221 раз
Поблагодарили: 88 раз

Re: Функция Рабочий/Выходной день

Сообщение webms » Ср янв 31, 2018 11:54 am

Dark_Veter писал(а):
sorochan.ilya писал(а):Интересная идея! По этой сылке: http://xmlcalendar.ru/data/ru/2016/calendar.xml XML файл с производственным календарем на 2016 год, соответственно после публикации на 2017 год ссылка будет http://xmlcalendar.ru/data/ru/2017/calendar.xml, может может кто к алисе прикрутить как приложение, чтобы сама обновляла свои знания о том какой сегодня день.
Вот, давно писал уже, не много костыльно, но вроде работает:

Код: Выделить всё

function weekDay($date) {
    $this_year = (int) date('Y', $date);
    //Загружаем производственный календарь
    $productionCalendar = @file_get_contents('http://xmlcalendar.ru/data/ru/' . $this_year . '/calendar.xml');
    if ($productionCalendar) { //Если прочитали без ошибок
        sg('DateTime.productionCalendar', $productionCalendar); //Запишем на всякий случай))
    } else { //Если не прочиталось
        $productionCalendar = gg('DateTime.productionCalendar'); // Возьмем ранее загруженный календарь
    }

    //Проверяем сегодняшний день по производственному календарю (рабочий или нет)
    $weekDay = -1;
    $this_date = date('m.d', $date);
    $calend = new SimpleXMLElement($productionCalendar);
    foreach ($calend->days->day as $day) {
        $type = $day->attributes()->t; //тип дня: 1 - выходной день, 2 - короткий день, 3 - рабочий день (суббота/воскресен)
        $CalDate = $day->attributes()->d; //дата
        if ($this_date == $CalDate) {
            if ($type == 1) { //выходной
                $weekDay = 0;
            } elseif ($type == 2) {
                //Короткий день
                //$weekDay = 1;
            } elseif ($type == 3) { //Перенесенный рабочий
                $weekDay = 0;
            }
        }
    }
    //Если в производственном календаре ничего не нашлось
    if ($weekDay == -1) {
        if (date('w', $date) == 0 || date('w', $date) == 6) {
            $weekDay = 0;
        } else {
            $weekDay = 1;
        }
    }
    return $weekDay;
}
В 00 часов обновляется и записывает в свойство. В коннексе у меня можно посмотреть.
что я делаю не так?) запускаю скрипт но ничего не работает

*** Сообщение запрещено. Сообщение похоже на спам. ***
Ответить