Имя: Пароль:
1C
 
Лет, месяцев и дней между датами
0 Эльниньо
 
12.11.10
11:31
Срочно понадобилось. Поделитесь алгоритмом расчёта кол-ва лет, дней и месяцев между датами, плз.
Начал делать так:

ВДнях = Конец - Начало;
Лет = ВДнях / 365;
Ост = ВДнях % 365;
Месяцев = Ост / 30;
Дней = Ост % 30;

Ясен пень неправильно.
1 mikecool
 
12.11.10
11:31
(0) для стажа?
2 1Сергей
 
12.11.10
11:33
нужно цикл. в нем Добавить месяц и считать
3 Эльниньо
 
12.11.10
11:33
(1) Не только. В ЗИКе наверное есть, но у меня под рукой нет. Времени у меня час, а занят другим.
4 Эльниньо
 
12.11.10
11:33
(2) Спасибо. А вискокосные как?
5 mikecool
 
12.11.10
11:34
+1 если да, то там используется год из расчета 360 дней,
в 2003 экселе есть функции долягода и год360(кажется)
6 1Сергей
 
12.11.10
11:34
(4) такая конструкция учтет
7 mikecool
 
12.11.10
11:34
+5 т.е. если человек отработал 360 дней в году - то это полный год
8 mikecool
 
12.11.10
11:35
(3) как раз для стажа твой механизм и правильный, но могу ошибаться...
9 Эльниньо
 
12.11.10
11:39
(8) Мой механизм даёт - 3 года, 12(!) месяцев и 27 дней для: 21.11.07 - 12.11.10
10 Mort
 
12.11.10
11:45
(0) Из за того что разное количество дней в месяцах, сплошной гимор. Например, вариант в столбик:

(----.12.31) - "разрядность"

2010.11.12
-
2007.11.21
------------
   2.11.22  

В любом случае для одинаковой разницы в днях, может быть разное количество в месяцах...
11 Lexxxxx
 
12.11.10
11:55
Кусок из ЗиК:

Если ПустоеЗначение(ФЛ.ОбщийСтаж) = 0  Тогда
  Разн = глРазницаВМесяцах(ФЛ.ОбщийСтаж,ДатаЗаполнения);
  Если Разн = 0  Тогда
     ВыслугаСтаж = "    днів       місяців      років";
  Иначе
     ОбщихМесяцев = Разн%12;
     ОбщихЛет = (Разн - ОбщихМесяцев) / 12;
     ОбщихДней = ДатаЗаполнения - ДобавитьМесяц(ФЛ.ОбщийСтаж,Разн);
     ОбщийСтаж = Формат(ОбщихДней, "Ч2") + глФормаМЧ(" день"," дні"," днів",ОбщихДней) + " " + Формат(ОбщихМесяцев, "Ч2") + глФормаМЧ(" місяць"," місяці"," місяців",ОбщихМесяцев) + " " + Формат(ОбщихЛет, "Ч2") + глФормаМЧ(" рік"," роки"," років",ОбщихЛет);
  КонецЕсли;        
Иначе
  ВыслугаСтаж = "    днів       місяців      років";
КонецЕсли;
12 Lexxxxx
 
12.11.10
11:55
Функция глРазницаВМесяцах(Д1,Д2)  Экспорт
   Годы = ДатаГод(Д2)-ДатаГод(Д1);
   Если Годы < 0 Тогда
       Годы = Годы + 100;
   КонецЕсли;
   Разн = ДатаМесяц(Д2) - ДатаМесяц(Д1) + Годы*12;
   Если ДатаЧисло(Д2) < ДатаЧисло(Д1) Тогда
       Разн = Разн-1;
   КонецЕсли;
   Возврат Разн;
КонецФункции
13 de Bug
 
12.11.10
11:56
Процедура глРазобратьРазностьДат(Знач Дата1,Знач Дата2,Лет=0,Месяцев=0,Дней=0) Экспорт

   Лет = 0; Месяцев = 0; Дней = 0;
   Если Дата1>Дата2 Тогда
       
       ВременнаяДата = Дата1;
       Если ДатаЧисло(ВременнаяДата)<ДатаЧисло(Дата2) Тогда
           Дней = ВременнаяДата-ДобавитьМесяц(ВременнаяДата,-1);
           ВременнаяДата = ДобавитьМесяц(ВременнаяДата,-1);
       КонецЕсли;
       Если ДатаМесяц(ВременнаяДата)<ДатаМесяц(Дата2) Тогда
           ВременнаяДата = ДобавитьМесяц(ВременнаяДата,-12);
           Месяцев = 12;
       КонецЕсли;
       Лет        = Макс(             ДатаГод  (ВременнаяДата)-ДатаГод  (Дата2),0);
       Месяцев    = Макс(Месяцев    +ДатаМесяц(ВременнаяДата)-ДатаМесяц(Дата2),0);
       Дней    = Макс(Дней        +ДатаЧисло(ВременнаяДата)-ДатаЧисло(Дата2),0);
       
       // скорректируем отображаемое значение, если "вмешалось" разное количество дней в месяцах
       Если Дата2 <> (ДобавитьМесяц(Дата1,-Лет*12-Месяцев)-Дней) Тогда
           Дней = Дней + (КонМесяца(Дата2)-НачМесяца(Дата2)) - (КонМесяца(ДобавитьМесяц(Дата1,-1))-НачМесяца(ДобавитьМесяц(Дата1,-1)));
       КонецЕсли;
   КонецЕсли;

КонецПроцедуры    // глРазобратьРазностьДат
14 Эльниньо
 
12.11.10
12:35
Сляпал:
//_____________________________________________________________________________
Процедура ПриЗаписи()
   Если (ПустоеЗначение(Начало) = 0) И (ПустоеЗначение(Конец) = 0) И (Конец > Начало) Тогда
       ВДнях = Конец - Начало;
       ДатаГ = Начало;
       Д = ДатаГ;
       Г = 0;
       Пока Д < Конец Цикл
           Д = ДобавитьМесяц(ДатаГ, 12);
           Если Д < Конец Тогда
               ДатаГ = Д;
               Г = Г + 1;
           КонецЕсли;
       КонецЦикла;
       М = 0;
       Д = ДатаГ;
       Пока Д < Конец Цикл
           Д = ДобавитьМесяц(ДатаГ, 1);
           Если Д < Конец Тогда
               ДатаГ = Д;
               М = М + 1;
           КонецЕсли;
       КонецЦикла;
       Дней = Конец - ДатаГ;
       Месяцев = М;
       Лет = Г;
   КонецЕсли;
КонецПроцедуры
15 Tatitutu
 
12.11.10
12:38
намного проще, код открытый
http://www.magazka.com/utility-i-dopolneniya/kalendar-na-vse-vremena.html
16 Жан Пердежон
 
12.11.10
12:41
(14) ты ведь видишь свои ошибки?)
17 Эльниньо
 
12.11.10
12:51
(16) Нет. Голова другим занята. Укажи, будь добр.
18 Жан Пердежон
 
12.11.10
13:00
c 01.01.10-01.02.10 - 0 месяцев 31 день
вместо 1 месяц 0 дней
19 Попытка1С
 
12.11.10
13:04
(17) в (13) функция из ЗИКа, чем не устраивает?
20 ildary
 
12.11.10
13:07
Делал что-то вот такое (на основе магазки из ссылки выше или еще откуда):


Функция   ГодВисокосен( Год )
   
   Возврат ?(  ( ( Год % 4   ) =  0 )
             И (
                      ( ( Год % 100 ) <> 0 )
                  ИЛИ ( ( Год % 400 ) =  0 )
               )
           , 1, 0
            );
   
КонецФункции //ГодВисокосен

Функция   КолвоДнейВГоду( ДатаГода )
   
   Год = ДатаГод( ДатаГода );
   
   ПервыйДеньМарта = Дата( "01.03." + Год );
   
   Если ( ПервыйДеньМарта - ДатаГода ) > 1 Тогда
       
       Год = Год - 1;
       
   КонецЕсли;
   
   Возврат 365 + ГодВисокосен( Год );
   
КонецФункции //

Процедура глРазобратьРазностьДат( Знач Дата1, Знач Дата2, Лет = 0, Месяцев = 0, Дней = 0,НеПрибавлятьДату = 0 ) Экспорт
// возвращает разницу между Дата1 и Дата2, где Дата1 - конец периода, т.е. Дата1 > Дата2
//
// НеПрибавлятьДату = 0 - у функций,  с пересчетом по годам (общий стаж)
// НеПрибавлятьДату = 1 - у функций, без пересчета по годам (отпуск)

   Если НеПрибавлятьДату = 0 Тогда //Дата1 = Дата1 + 1 - т.к. мы у круглого года вынуждены были дату убавить
       
       Дата1 = Дата1 + 1;
       
   КонецЕсли;
   
   Лет = 0; Месяцев = 0; Дней = 0;
   
   Если Дата1 <= Дата2 Тогда //Возврат
       
       Возврат;
       
   КонецЕсли;
   
   ВременнаяДата = Дата1;
   
   Если ДатаЧисло( ВременнаяДата ) < ДатаЧисло( Дата2 ) Тогда
       
       Дней = ВременнаяДата - ДобавитьМесяц( ВременнаяДата, -1 );
       ВременнаяДата = ДобавитьМесяц( ВременнаяДата, -1 );
       
   КонецЕсли;
   
   Если ДатаМесяц( ВременнаяДата ) < ДатаМесяц( Дата2 ) Тогда
       
       ВременнаяДата = ДобавитьМесяц( ВременнаяДата, -12 );
       Месяцев          = 12;
       
   КонецЕсли;
   
   Лет     = Макс(           ДатаГод(   ВременнаяДата ) - ДатаГод(   Дата2 ), 0 );
   Месяцев = Макс( Месяцев + ДатаМесяц( ВременнаяДата ) - ДатаМесяц( Дата2 ), 0 );
   Дней    = Макс(    Дней + ДатаЧисло( ВременнаяДата ) - ДатаЧисло( Дата2 ), 0 );
   
   // скорректируем отображаемое значение, если "вмешалось" разное количество дней в месяцах
   Если Дата2 <> ( ДобавитьМесяц( Дата1, -Лет * 12 - Месяцев ) - Дней ) Тогда
       
       Дней = Дней + ( КонМесяца( Дата2 ) - НачМесяца( Дата2 ) )
                   - ( КонМесяца( ДобавитьМесяц( Дата1, -1 ) )
                      -НачМесяца( ДобавитьМесяц( Дата1, -1 ) ) );
   КонецЕсли;

КонецПроцедуры //глРазобратьРазностьДат

Функция   ПолучитьСтрокуРазностиДат( Лет, Месяцев, Дней )
   
   //++ исправим количество дней и мес
   
   Если Дней > 30 Тогда
       
       Дней    = Дней    - 31;
       Месяцев = Месяцев +  1;
       
   КонецЕсли;
   
   Если Месяцев > 11 Тогда
       
       Месяцев = Месяцев - 12;
       Лет        = Лет      +  1;
       
   КонецЕсли;
   
   //== исправим количество дней и мес
   
   Стр = ?( ПустоеЗначение( Лет     ) = 1, "", "" + Лет + " г" );
   
//Месяцев = Месяцев + Окр( Дней / 30, 1 );
   
   Стр = Стр + ?( ПустоеЗначение( Месяцев ) = 1, "", ?( ПустоеЗначение( Стр ) = 1, "", ", ") + Месяцев + " м" );
   Стр = Стр + ?( ПустоеЗначение( Дней       ) = 1, "", ?( ПустоеЗначение( Стр ) = 1, "", ", ") + Дней    + " дн" );
   
   Возврат Стр;
   
КонецФункции // ПолучитьСтрокуразностиДат

Функция   глРазностьДатСтрокой( Знач Дата1, Знач Дата2, НеПрибавлятьДату = 0 )
// НеПрибавлятьДату = 0 - у функций,  с пересчетом по годам (общий стаж)
// НеПрибавлятьДату = 1 - у функций, без пересчета по годам (отпуск)

   Лет = 0; Месяцев = 0; Дней = 0;
   глРазобратьРазностьДат( Дата1, Дата2, Лет, Месяцев, Дней, НеПрибавлятьДату );
   
   Возврат ПолучитьСтрокуРазностиДат( Лет, Месяцев, Дней );

КонецФункции //глПолучитьРазностьДатСтрокой
21 Жан Пердежон
 
12.11.10
13:20
(19) между 31.01.10 и 01.03.10
1 месяц и 3 дня?
22 Эльниньо
 
12.11.10
13:33
(13)(20)(21) Спасибо.
23 Злопчинский
 
12.11.10
14:06
.. мало того, если к текущей дате прибавить месяц, а потом отнять месяц - хрен вы вернетесь в исходную дату...
24 Эльниньо
 
12.11.10
14:08
(22) У меня: 1 месяц и 1 день
25 Has
 
12.11.10
14:27
вариант логики на примере
28.10.10 - 03.02.12

2011= 1 год
нояб10+дек10+янв12=3мес
29окт2010+30окт2010+31окт2010+01февр2012+02февр2012=5дней
26 SiAl-chel
 
12.11.10
16:04
Я бы просто циклом перебирал.
1. выбрал бы меньшую дату
2. к меньшей добавлял бы по 12 месяцев, пока не превысил большую дату,  - количество лет
3. потом к (меньшая + лет * 12) прибавлял в цикле месяца, получил бы количество месяцев
3. а количество дней - это уже остаток от двух предыдущих циклов.
27 Эльниньо
 
12.11.10
17:01
(26) См.(14)
Закон Брукера: Даже маленькая практика стоит большой теории.