| 
| 
 | Вопрос # 6 041/ вопрос решён / | 
 |  Здравствуйте уважаемые эксперты! Как в Delphi вычислить количество рабочих часов в текущем месяце и занести результат, например, в компонет TextEdit, при условии, что: 5-ти дневная, 8-ми часовая рабочая неделя, два выходных: суббота, воскресенье. Если есть праздничные дни их тоже исключить из расчета рабочего времени. Если можно, приведите подробный пример. Заранее Спасибо! 
|  |   Вопрос задал: stales (статус: 1-ый класс)Вопрос отправлен: 2 апреля 2012, 11:01
 Состояние вопроса: решён, ответов: 1.
 |  Ответ #1. Отвечает эксперт: Мережников Андрей Здравствуйте, stales!Неправильно работает потому, что неправильно используется функция DayOfWeek - значение 1 - воскресенье, 7 - суббота (достаточно посмотреть хелп). Вот пример функции - на работоспособность не проверял. Данная функция не в состоянии определить праздничный нерабочий день, так же, как и не может знать о переносах выходных.
 
 function WorkDay(d:TDate;c: byte = 5):Integer;
var vd,endD:TDate;
    Yr,Mn,Dy:integer;
begin
  Result:=0;
  DecodeDate(d,Yr,Mn,Dy);
  vd:=EncodeDate(Yr,Mn,1);
  endD:=EndOfAMonth(Yr,Mn);
  while vd<=endD
  do begin
       if DayOfTheWeek(vd)<6
       then inc(Result)
       else if (c>5)and(DayOfTheWeek(vd)=6)
            then inc(Result);
       vd:=IncDay(vd);
     end;
end;
|  | Ответ отправил: Мережников Андрей (статус: Абитуриент)Время отправки: 2 апреля 2012, 18:18
 Оценка за ответ: 5
 Комментарий к оценке: Андрей Спасибо! Получилось! Только не много пришлось подправить код. Там где у Вас идет объявление переменныхvar vd, endD: Tdate;
 Yr, Mn, Dy: Word - вот нужно было какой параметр поставить и все, код заработал! Огромное спасибо!!!
 |  
 Мини-форум вопросаВсего сообщений: 5; последнее сообщение — 2 апреля 2012, 13:47; участников в обсуждении: 2. 
|   | min@y™ (статус: Доктор наук), 2 апреля 2012, 11:35 [#1]:Чо тут сложного? Берём апрель 2012... 
  
    2  9 16 23 30
    3 10 17 24
    4 11 18 25
    5 12 19 26
    6 13 20 27
    7 14 21 28
 1  8 15 22 29В апреле 30 дней. Выкидываем выходные с праздниками: 1, 7, 8, 14, 15, 21, 22, 29, 30. Остаётся 21 рабочий день. Умножаем на 8 часов, получается 168.
 TextEdit.Text:= IntToStr(8 * WorkDaysCount);Вуаля! В чём проблема-то?
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | stales (статус: 1-ый класс), 2 апреля 2012, 11:57 [#2]:Спасибо, попробую. Может еще есть какие предложения у кого? |  
|   | stales (статус: 1-ый класс), 2 апреля 2012, 12:09 [#3]:Не совсем понятно, как программным путем откинуть выходные дни и оставить 21 рабочий? Подробный код бы реализации данного расчета. |  
|   | min@y™ (статус: Доктор наук), 2 апреля 2012, 13:12 [#4]: Цитата (stales): Не совсем понятно, как программным путем откинуть выходные дни и оставить 21 рабочий? Для этого программе нужны исходные данные, которые кем-то должны быть заданы, например, начальством. На разных предприятиях они могут быть разными, как ни крути. Я щас просто посмотрел на общезаводской календарь (его плановый отдел выпускает каждый год).
 Если данные есть, то просто считай количество выходных и праздников и вычитай его из количества дней в месяце.
 
 Цитата (stales): как программным путем откинуть Ну а как я тебе это объясню, если не знаю, каким макаром у тебя хранятся даты выходных и праздников?
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | stales (статус: 1-ый класс), 2 апреля 2012, 13:47 [#5]:Вот нашел похожий вопрос и там есть не большой исходник, но автор говорит, что не много не правильно он работает на некоторых месяцах. Может Вам удастся подправить его? Вот цитата оттуда: ---------
 function Workday(d:TDate;c: byte = 5):Integer;
 //c=5 если пятидневная рабочая неделя,
 //если шестидневная - другое число
 var f,l,wday:integer;
 Year,Month,Day:Word;
 s:TDate;
 begin
 DecodeDate(d,Year,Month,Day);
 l:=DaysInMonth(d);
 f:=1; wday:=1;
 if c=5 then begin
 repeat
 s:=EncodeDate(Year,Month,f);
 case DayOfWeek(s) of
 1..5: wday:=wday+1;
 end;
 f:=f+1;
 until
 f=l;
 end else begin
 repeat
 s:=EncodeDate(Year,Month,f);
 case DayOfWeek(s) of
 1..6: wday:=wday+1;
 end;
 f:=f+1;
 until
 f=l;
 end;
 result:=wday;
 end;
 
 вроде работает но вот в некоторых месяцах делет ошибку.
 а использование следующим образом:
 
 Label1.Caption:=IntToStr(Workday(fsDateTimePicker1.Date,5));
 
 может у кого есть менее громозкий код, поделитесь.
 --------------
 |  4 апреля 2012, 11:20: Статус вопроса изменён на решённый (изменил автор вопроса — stales) Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |