Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Посчитать количество рабочих дней 
:(
    Опции темы
Gold Dragon
Дата 12.1.2014, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



Есть дата договора. Есть количество дней (рабочих) на исполнение, т.е. без субботы и воскресенья.

Как минимальными затратами вычислить дату окончания договора?


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 12.1.2014, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



в предположении, что дата договора попадает на рабочий день недели
<остаток>=<рабочих дней>%5
<дней всего>=7*<рабочих дней>/5+<остаток>+max(0,<остаток>?<день недели даты договора>-3:0)

Это сообщение отредактировал(а) baldina - 12.1.2014, 20:38
PM MAIL   Вверх
Gold Dragon
Дата 12.1.2014, 20:49 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



если честно, то ничего не понял. И мне не нужны проценты вероятности. мне нужна точная дата (государственные праздники не в счёт).

Запросов должно быть много, так что код должен быть оптимизированный... 

ps
может есть какая готовая функция? что-то я не нашёл


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
ksnk
Дата 12.1.2014, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Разумнее, imho, вести базу нерабочих дней. То есть каждая запись в базе выглядит {день:XXX}. В базу попадаю все выходные и праздничные дни. Из базы выкидываются все рабочие дни и дни переноса "праздников". Заполняются вручную + полуавтомат про выходные. Сама табличка не особенно большая, к тому же ее можно чистить от устаревших данных.
Для небольшого временнОго периода (неделя?), можно вычислять рабочие дни перебирая дни в цикле. Проверка - есть ли день в базе, если нету, значит рабочий. 
Для длинного диапазона - считаем, что от начальной даты должно пройти 7/5 дней от количества рабочих. Получаем диапазон. Выкидываем оттуда количество всех праздничных дней, из базы. получаем количество рабочих дней. Если рабочих дней нужно меньше или больше - отнимаем или прибавляем рабочие дни, как в первом случае.



--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
Gold Dragon
Дата 12.1.2014, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



с базой не самый оптимальный вариант, но зато можно предусмотреть все праздники.. Нужно прикинуть...

я так понимаю, мне нужно посчитать количество недель и добавить по 2 дня для каждой недели. Плюсь сделать поправку на полную неделю, т.е. начало и конец


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 12.1.2014, 22:21 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(Gold Dragon @  12.1.2014,  21:37 Найти цитируемый пост)
я так понимаю, мне нужно посчитать количество недель и добавить по 2 дня для каждой недели. Плюсь сделать поправку на полную неделю, т.е. начало и конец 

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

но вообще ksnk прав, если это реальная задача, праздники тоже надо учитывать. и база - самый разумный вариант. её размер будет невелик, так что скорость достаточно высока.

Добавлено @ 22:35
Код

function end_date ($start_date, $working_days) {
  $modulo = $working_days%5;
  $weekday = date ('N', $start_date);
  $days=7*(int)($working_days/5)+$modulo+max(0,$modulo?$weekday-3:0);
  return // $start_date + $days
}

разжевал. в рот сам положишь?  smile 

Это сообщение отредактировал(а) baldina - 12.1.2014, 22:59
PM MAIL   Вверх
Gold Dragon
Дата 12.1.2014, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



baldina, так если бы ты кодом писал сразу, а то алгоритмами.. вот и гадай что такое %5  smile 
а за разжевал +1  smile 

а вот по базе вопрос.. Мне необходимо "пробежаться" по базе договоров, допустим их порядка 500-1000 и высчитать просрочку.. Не сильно ли это подвисать будет? Хотя если кеш умный сделать...

Это сообщение отредактировал(а) Gold Dragon - 12.1.2014, 23:20


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 12.1.2014, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(Gold Dragon @  12.1.2014,  23:17 Найти цитируемый пост)
Мне необходимо "пробежаться" по базе договоров, допустим их порядка 500-1000 и высчитать просрочку

1000 это очень, очень немного...
Да и не нужна по 1000 договоров такая инфа, максимум по одному. Либо это некий отчет, а отчеты могут генериться не мгновенно, это нормально.

Добавлено через 3 минуты и 4 секунды
кстати. те же подсчеты можно прямо в запросе к базе проводить. и что-то мне подсказывает, что они будут быстрее php... и медленнее join таблицы праздников.
PM MAIL   Вверх
Gold Dragon
Дата 12.1.2014, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



Цитата(baldina @  13.1.2014,  00:26 Найти цитируемый пост)
Либо это некий отчет, а отчеты могут генериться не мгновенно, это нормально.
Это типа корпоративный сайт, и это в том числе отчёты smile

В общем нужно скорость проверять в реальных условиях...



--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
maxipub
Дата 13.1.2014, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 517
Регистрация: 22.10.2009

Репутация: нет
Всего: 1



Получаем timestamp начальной даты, и в цикле прибавляем к нему 86400, пока не дойдем до конечной даты, инкрементируя счетчик рабочих дней, где date('w', $timestamp) не 0, и не 6 (вс=0, сб=6). Может быть не минимальные затраты, но все же 5-6 строй кода. Да и корректней будет считать.

ЗЫ: лет 10 сижу на форуме, всегда только спрашивал, что это сегодня решил ответить? smile  smile  smile

Добавлено через 2 минуты и 23 секунды
Цитата(Gold Dragon @  12.1.2014,  23:17 Найти цитируемый пост)
Мне необходимо "пробежаться" по базе договоров, допустим их порядка 500-1000 и высчитать просрочку..

0.05 сек, не более
PM MAIL   Вверх
Fortop
Дата 13.1.2014, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 20
Всего: 42



Цитата(maxipub @  13.1.2014,  14:04 Найти цитируемый пост)
 что это сегодня решил ответить? 


Цитата(maxipub @  13.1.2014,  14:04 Найти цитируемый пост)
Получаем timestamp начальной даты, и в цикле прибавляем к нему 86400, пока не дойдем до конечной даты

В таком духе лучше не отвечать smile


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
Gold Dragon
Дата 23.1.2014, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



baldina, что-то твой код не хочет рабоать.. уже устал его ломать smile 
например, задаю даты с шагом один день, получаю в два. Или задаю нчало договора в выходной, вообще как-то странно считает


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 24.1.2014, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(Gold Dragon @  23.1.2014,  21:42 Найти цитируемый пост)
задаю нчало договора в выходной


Цитата(baldina @  12.1.2014,  20:31 Найти цитируемый пост)
в предположении, что дата договора попадает на рабочий день недели


Цитата(Gold Dragon @  23.1.2014,  21:42 Найти цитируемый пост)
задаю даты с шагом один день, получаю в два

дата договора за день считается: договор может закончиться в тот же день, но не раньше. если надо можешь вычесть 1
http://ideone.com/Ao5zCk
PM MAIL   Вверх
Gold Dragon
Дата 24.1.2014, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



а если так
Код

$start_date = date_timestamp_get(date_create ('2014-01-01'));
for ($i=10; $i < 15; ++$i) {
echo date ('d/m/Y',end_date($start_date,$i)), PHP_EOL;
}

то дата окончания 
Цитата
...
18/01/2014
19/01/2014

А это выходные


PS
выходные - рассматриваем только субботу и воскресенье

Добавлено через 3 минуты и 22 секунды
а если так
Код

$start_date = date_timestamp_get(date_create ('2014-01-04'));
for ($i=10; $i < 15; ++$i) {
echo date ('d/m/Y',end_date($start_date,$i)), PHP_EOL;
}


то имеем
Цитата

18/01/2014 - сб
22/01/2014 - ср
23/01/2014 - чт
24/01/2014 - пт
25/01/2014 - сб


Это сообщение отредактировал(а) Gold Dragon - 24.1.2014, 13:43


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
capitan
Дата 24.1.2014, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 27.2.2005
Где: Москва

Репутация: 9
Всего: 13



Была подобная задача. Показывать дату доставки учитывая выходные, праздники + смещение.

Код

// Исходные данные
    define ('DELIV_SHIFT', 2) ; //смещение доставки ч + дней
    
    // Массив праздников. Ключ - месяц
    $holiday_days = array();
    $holiday_days[1] = array(1,2,3,4,5,6,7,8);
    $holiday_days[2] = array(23);
    $holiday_days[3] = array(8,10);
    $holiday_days[5] = array(1,9);
    $holiday_days[6] = array(12);
    $holiday_days[11] = array(3,4);
    
    
    $date=date("d.m.Y"); // Сегодня
    echo CheckHoliday($date, 0);
        
    function CheckHoliday($date, $count) {    
        global $holiday_days;
        
        $dayName = date('N', strtotime($date));
        $new_data = date("d.m.Y", strtotime($date ."+1 day"));    
                        
        if($dayName == 6 || $dayName == 7) {            
            return CheckHoliday($new_data, $count);
        } else {
            $check_day = date('j', strtotime($new_data));
            $check_month = date('n', strtotime($new_data));
            if(in_array($check_day, $holiday_days[$check_month])) {                    
                return CheckHoliday($new_data, $count);
            } else {
                if($count <= DELIV_SHIFT) {
                    $count +=1;
                    return CheckHoliday($new_data, $count);
                } else {
                    return $date;
                }
                
            }
        }        
    }


PM MAIL WWW ICQ   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0690 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.