gifts2017

Вновь о том, как рассчитать стаж

Опубликовал trest30 Калыев (trest30) в раздел Программирование - Практика программирования

Простой прием (алгоритм) расчета стажа

При создании конфигурации для кадров столкнулся в необходимости расчета стажа... Понятно, что все это уже делалось и, возможно, я изобретаю велосипед, но пусть это будет мой мопед. Возможно, кому-то пригодится, и для кого-то это окажется наиболее простым решением 

Функция РазностьДат(ДатаНач, ДатаКон) Экспорт

В начале узнаем, сколько полных лет в стаже

Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| РАЗНОСТЬДАТ(&ДатаНач, &ДатаКон, МЕСЯЦ) КАК Месяцы"
;
Запрос.УстановитьПараметр("ДатаНач", ДатаНач);
Запрос.УстановитьПараметр("ДатаКон", ДатаКон);
Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий();
Если Выборка.Месяцы > 12 ИЛИ (Выборка.Месяцы = 12 И День(ДатаНач) < День(ДатаКон)) Тогда
Годы = Цел(Выборка.Месяцы / 12);

Далее отсекаем количество отработанных лет (запоминая их), чтобы остались месяцы и дни

ДатаД = ДобавитьМесяц(ДатаНач,Годы * 12); 
Иначе
Годы = 0; 
ДатаД = ДатаНач;
КонецЕсли;

Определяем количество отработанных месяцев

ЗапросД = Новый Запрос;
ЗапросД.Текст = "
|ВЫБРАТЬ
| РАЗНОСТЬДАТ(&ДатаНачД, &ДатаКонД, МЕСЯЦ) КАК Месяцы"
;
ЗапросД.УстановитьПараметр("ДатаНачД", ДатаД);
ЗапросД.УстановитьПараметр("ДатаКонД", ДатаКон);
ВыборкаД = ЗапросД.Выполнить().Выбрать();
ВыборкаД.Следующий();

Проверим, когда конечная дата и дата приема в одном месяце (включается или нет последний месяц)

Если ДобавитьМесяц(ДатаД,ВыборкаД.Месяцы) > ДатаКон Тогда
Месяцы = ВыборкаД.Месяцы - 1;
Иначе
Месяцы = ВыборкаД.Месяцы;
КонецЕсли;

Ну и количество дней найдем

ДатаК = ДобавитьМесяц(ДатаД,Месяцы);
ЗапросК = Новый Запрос;
ЗапросК.Текст = "
|ВЫБРАТЬ
| РАЗНОСТЬДАТ(&ДатаНачК, &ДатаКонК, ДЕНЬ) КАК Дни"
;
ЗапросК.УстановитьПараметр("ДатаНачК", ДатаК);
ЗапросК.УстановитьПараметр("ДатаКонК", ДатаКон);
ВыборкаК = ЗапросК.Выполнить().Выбрать();
ВыборкаК.Следующий(); 
Дни = ВыборкаК.Дни;
МассивДат = Новый Массив;
МассивДат.Добавить(Годы);
МассивДат.Добавить(Месяцы);
МассивДат.Добавить(Дни);
Возврат(МассивДат);
КонецФункции

Ну вот и все...Функция возвращает массив, где первый элемент годы, второй месяцы и третий дни

Затем можно вызвать данную функцию для вывода стажа, например, так

МассивДат = РазностьДат(ДатаПриема,ТекущаяДата());
Если Прав(МассивДат[0], 1) = "1" 
ИЛИ Прав(МассивДат[0], 1) = "2" 
ИЛИ Прав(МассивДат[0], 1) = "3"
ИЛИ Прав(МассивДат[0], 1) = "4"
Тогда п = " г. ";
Иначе п = " л. ";
КонецЕсли;
Стаж = Строка(МассивДат[0]) + п + Строка(МассивДат[1]) + " м. " + Строка(МассивДат[2]) + " д";

 

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Андрей Карпов (karpik666) 28.04.15 04:37
А вы в курсе, что есть разные виды стажа? И то, что если сотрудник берет административку, то она не учитывается в стаже? В общем, простой разностью дат это не решается, откройте зуп и посмотрите там, как вычисляется стаж. Понятно, что изобрели велосипед, так велосипед, ведь должен работать с точки зрения законодательства.
2. trest30 Калыев (trest30) 28.04.15 06:09
(1) karpik666, Это все понятно, просто здесь описан сам алгоритм нахождения разности дат, и эта функция может применяться в зависимости от Ваших потребностей и условий расчета..
3. Андрей Карпов (karpik666) 28.04.15 06:59
тогда -
Код вообще не оптимизирован - 2 запроса, чтобы получить разность дат. И можно было сразу получить все данные через запрос.
Вот мой пример получения стажа, без использования запросов. И то я абсолютно точно уверен, что есть более удобные и элегантные решения.
Функция СтажРаботы(ДатаНач, ДатаКон)
	Если ДатаКон < ДатаНач Тогда
		Возврат "Дата начала больше даты окончания. Стаж не рассчитан";		
	КонецЕсли; 
	Если ДатаКон = ДатаНач Тогда
		Возврат "Даты равны.";	
	КонецЕсли; 
	СтруктураДатаНач = Новый Структура;
	СтруктураДатаНач.Вставить("Год", Год(ДатаНач));
	СтруктураДатаНач.Вставить("Месяц", Месяц(ДатаНач));
	СтруктураДатаНач.Вставить("День", День(ДатаНач));
	СтруктураДатаКон = Новый Структура; 
	СтруктураДатаКон.Вставить("Год", Год(ДатаКон));
	СтруктураДатаКон.Вставить("Месяц", Месяц(ДатаКон));
	СтруктураДатаКон.Вставить("День", День(ДатаКон));
	Если СтруктураДатаКон.День < СтруктураДатаНач.День Тогда
		СтруктураДатаКон.Месяц = СтруктураДатаКон.Месяц - 1;	
		СтруктураДатаКон.День = СтруктураДатаКон.День + День(КонецМесяца(ДобавитьМесяц(ДатаКон,-1))); 
	КонецЕсли; 
	
	СтажДней = СтруктураДатаКон.День - СтруктураДатаНач.День;
	
	//Если это января, тогда может быть, что разность затрагивает целый год
        Если СтруктураДатаКон.Месяц < СтруктураДатаНач.Месяц Тогда
		СтруктураДатаКон.Месяц = СтруктураДатаКон.Месяц + 12;
		СтруктураДатаКон.Год = СтруктураДатаКон.Год - 1;
	КонецЕсли;
	
	СтажМесяцев = СтруктураДатаКон.Месяц - СтруктураДатаНач.Месяц;
	СтажЛет =  СтруктураДатаКон.Год - СтруктураДатаНач.Год;
	
	Возврат ?(СтажЛет = 0, "", ЧислоПрописью(СтажЛет,,"год, года, лет, м, , , , м,0") + ", ") + 
			?(СтажМесяцев = 0, "", ЧислоПрописью(СтажМесяцев,,"месяц, месяца, месяцев, м, , , , м,0") + ", ") +
			 ЧислоПрописью(СтажДней,,"день, дня, дней, м, , , , м,0");	
КонецФункции
...Показать Скрыть
4. rasswet (rasswet) 29.04.15 10:55
для полноты картины. Если воспользоватся типовыми механизмами расчета стажа в ЗУП 2.5 и ЗУП 3,0 при опредленных входящих данных мы получим разные результаты.
Также еще есть вопрос как складывать несколько периодов стажа. как округлять дни в месяцы.
Было несколько заказчиков - у каждого свой подход был к этому.
5. trest30 Калыев (trest30) 29.04.15 11:18
(4) rasswet,
как складывать несколько периодов стажа. как округлять дни в месяцы.
Ну иожно как вариант из конечную дату расчета сдвинуть назад на количество дней разрыва стажа...
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа