На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Вычисление разности двух дат в месяцах
    Подскажите кто знает, нужно выводить к-во отработанных лет,месяцев,дней (другими словами высчитать стаж). Сделал так, ниже код, но проблема с февралем, нужно трактовать занятый месяц: 1 месяц = 28, 29, 30, 31 дней? Вдобавок, дело осложняется с высокосностью годов.

    Если поставить с 01.02 по 28.02 должно получится 0 лет 1 месяц 0 дней (получается 0 лет 0 месяцев 28 дней), а с 01.02 по 01.03 0лет 1 месяц 1 день (получается 0 лет 0 месяцев 29 дней)

    ExpandedWrap disabled
      // день
      function StrDays(iDay: integer): string;
      begin
        Result:= ' дней ';
        case iDay of
          1, 21, 31: Result:= ' день ';
          2, 3, 4, 22, 23, 24: Result:= ' дня ';
        end;
      end;
       
      // месяц
      function StrMonths(iMonth: integer): string;
      begin
        Result:= ' месяцев ';
        case iMonth of
          1: Result:= ' месяц ';
          2, 3, 4: Result:= ' месяца ';
        end;
      end;
       
      // год
      function StrYears(iYear: integer): string;
      var
        s: string;
        sYear: string;
        i: integer;
      begin
        result := ' лет ';
        if (iYear > 4) and (iYear < 21) then exit;
        sYear := IntToStr(iYear);
        s := Copy(sYear, Length(sYear), 1);
        i := StrToInt(s);
        case i of
          1: result := ' год ';
          2, 3, 4: result := ' года ';
        end;
      end;
       
      // ф-я
      function StrBetweenDate(Date1, Date2: TDate): string;
      var
        id, im, iy: Integer;
        d: TDate;
      begin
        Result:= '';
        if Date1 < Date2 then
        begin
          d:= Date1;
          Date1:= Date2;
          Date2:= d;
          Date1:= Date1 + 1;
        end;
        d:= DaysBetween(Date1 + 1, Date2);
        id:= DayOf(d);
        im:= MonthOf(d)-1;
        iy:= YearOf(d);
        iy:= iy - 1900;
       
        if im = 12 then
          begin
            im:= 0;
            inc(iy);
          end;
       
       
        if id = 31 then
        begin
          id:= 0;
          inc(im);
       
          if im = 12 then
          begin
            im:= 0;
            inc(iy);
          end;
        end;
        Result:= (IntToStr(iy)+ StrYears(iy) + IntToStr(im) +
                  StrMonths(im) + IntToStr(id)+ StrDays(id));
      end;
       
      procedure TForm1.Button1Click(Sender: TObject);
      var
       aDate, date1: TDateTime;
       
      begin
           aDate := DateTimePicker1.Date;
       date1 := DateTimePicker2.Date;
       
      label5.Caption := StrBetweenDate(aDate, date1);
      В коде много странных действий типа прибавления одного дня к стартовой дате - но лишь в случае, если даты обмениваются.

      Выходные и праздники в расчёте не учитываются?

      Стоит выполнить DecodeDate и по очереди сравнивать:
      год c учётом комбинации месяц/день
      что-то вроде
      ExpandedWrap disabled
        YearsBetween = Year2 - Year1 - Ord((Month2  - Month1) * 31 + (Day2-Day1) < 0)

      месяц с учётом дня
        Цитата MBo @
        Выходные и праздники в расчёте не учитываются?
        учитываются и выходные праздничные дни
            Цитата MBo @
            Стоит выполнить DecodeDate и по очереди сравнивать:
            год c учётом комбинации месяц/день
            что-то вроде ...

            А зачем?
            Нужно просто увеличить бОльшую дату на 1 день, выполнить DecodeDate и просто взять разности соответствующих значений лет, месяцев и дней. При этом и разное кол-во дней в месяцах, и високосные годы будут учтены автоматически.
              Цитата
              просто взять разности соответствующих значений лет, месяцев и дней


              Что подразумевается под "просто взять разности"

              Разности покомпонентные 15 марта 2017 и 17 июля 2016 - получим 1 год, -4 месяца и -2 дня?
                pas2а по какому алгоритму предлагает считать стаж пенсионный фонд, смотрели? кто там у нас еще отчетность со стажем собирает, у них алгоритм один или разные?
                  Мне кажется, если учитываются именно фактические дни, а не календарная разница, то иначе как циклом наращивания високосные годы и месяцы не посчитать. IsLeapYear и константы кол-ва дней в месяцах из DateUtils помогут.
                  Цитата
                  if (iYear > 4) and (iYear < 21) then exit;
                  sYear := IntToStr(iYear);
                  s := Copy(sYear, Length(sYear), 1);
                  i := StrToInt(s);

                  Открой для себя оператор mod
                  Цитата pas2 @
                  function StrDays(iDay: integer): string;
                  function StrMonths(iMonth: integer): string;

                  Вот так это делается правильно http://www.unicode.org/cldr/charts/latest/...ural_rules.html
                    Цитата MBo @
                    Разности покомпонентные 15 марта 2017 и 17 июля 2016 - получим 1 год, -4 месяца и -2 дня?

                    Да, я ступил. По "простому" тут не получится
                    Тогда как-то так
                    ExpandedWrap disabled
                      DecodeDate(Date1,y1,m1,d1);
                      DecodeDate(Date2 + 1,y2,m2,d2);
                      dY:=y2-y1; dM:=m2-m1; dD:=d2-d1;
                      if (dM < 0) or (dM = 0) and (dD < 0) then
                      begin
                        dec(dY);
                        inc(dM,12);
                      end;
                      if dD < 0 then
                      begin
                        dec(dM);
                        if m2 = 1 then
                          inc(dD,31)
                        else
                          inc(dD,DaysInAMonth(y2,m2 - 1));
                      end;
                      вопрос,решен всем спасибо
                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,0400 ]   [ 16 queries used ]   [ Generated: 20.04.24, 03:52 GMT ]