В одном проекте понадобилось подсчитывать полное количество месяцев между датами,
Допустим надо получить кол-во месяцев между датами 25.10.14 и 21.11.14
Функция РазницаДатВМесяцах ( Как вычислить разницу между двумя датами в месяцах ) вернет 1 , по сути разница между датами = одному месяцу,
но по факту работы будут в 10 и 11 месяцах , т.е. всего 2, в итоге была написана простая функция, ее код ниже:
Код 1C v 8.2 УП тДат=ДатаНачала; КолМес = 0;
Пока Месяц(тДат)<> Месяц(ДатаОкончания) Цикл
КолМес = КолМес+1;
тДат = ДобавитьМесяц(тДат,1);
КонецЦикла;
Результат = КолМес+1;
Основная функция будет использовать в себе три вспомогательных:
Код 1C v 8.х Функция РазностьМеждуДатамиВМесяцах(Дата1,Дата2)
Год1 = Год(Дата1);
Год2 = Год(Дата2);
Месяц1 = Месяц(Дата1);
Месяц2 = Месяц(Дата2);
День1 = День(Дата1);
День2 = День(Дата2);
Результат = (Год1 - Год2) * 12 + Месяц1 - Месяц2;
Если Результат < 0 Тогда Результат = 0 - Результат; КонецЕсли;
Если ((Дата1 > Дата2) И (День1 < День2)) ИЛИ ((Дата1 < Дата2) И (День1 > День2)) Тогда
Результат = Результат - 1;
КонецЕсли;
Возврат Результат;
КонецФункции
Код 1C v 8.х Функция ВозрастВМесяцахИГодах(Месяцы)
Структура = Новый Структура;
Структура.Вставить("Год");
Структура.Вставить("Месяц");
Структура.Месяц = Месяцы % 12;
Структура.Год = (Месяцы - Структура.Месяц) / 12;
Возврат Структура;
КонецФункции
Код 1C v 8.х Функция ВозрастПрописью(Структура)
Строка = "";
Если Структура.Год > 0 Тогда
ПоследняяЦифраГода = Число(Сред(Строка(Структура.Год), СтрДлина(Строка(Структура.Год)), 1));
Если (ПоследняяЦифраГода = 1) И (Структура.Год <> 11) Тогда Строка = Строка(Структура.Год) + " год"; КонецЕсли;
Если (ПоследняяЦифраГода >= 2) И (ПоследняяЦифраГода <=4) И ((Структура.Год < 12) ИЛИ (Структура.Год > 14)) Тогда Строка = Строка(Структура.Год) + " года"; КонецЕсли;
Если ((ПоследняяЦифраГода >= 5) И (ПоследняяЦифраГода <=9)) ИЛИ (ПоследняяЦифраГода = 0) Тогда Строка = Строка(Структура.Год) + " лет"; КонецЕсли;
Если (Структура.Год >= 11) И (Структура.Год <= 14) Тогда Строка = Строка(Структура.Год) + " лет"; КонецЕсли;
КонецЕсли;
Если (Структура.Год > 0) И (Структура.Год < 3) И (Структура.Месяц > 0) Тогда
Строка = Строка + ", ";
КонецЕсли;
Если (Структура.Месяц > 0) И (Структура.Год <= 3) Тогда
Если Структура.Месяц = 1 Тогда Строка = Строка + "1 месяц"; КонецЕсли;
Если (Структура.Месяц >= 2) И (Структура.Месяц <= 4) Тогда Строка = Строка + Строка(Структура.Месяц) + " месяца"; КонецЕсли;
Если Структура.Месяц >= 5 Тогда Строка = Строка + Строка(Структура.Месяц) + " месяцев"; КонецЕсли;
КонецЕсли;
Возврат Строка;
КонецФункции
А вот и основная:
Код 1C v 8.х Функция ВозрастВычислить(Возраст,Дата)
Месяцы = РазностьМеждуДатамиВМесяцах(Возраст,Дата);
ВозрастСтруктура = ВозрастВМесяцахИГодах(Месяцы);
ВозрастПрописью = ВозрастПрописью(ВозрастСтруктура);
Возврат ВозрастПрописью;
КонецФункции
Изменения 2011.07.26: Небольшие доработки в процедуре
ВозрастПрописью - теперь всё работает правильно.
Нужно получить разницу между датами
31.12.2009 и
10.01.2005 и отобразить ее как:
4 года 11 месяцев 21 день
Код 1C v 8.х Процедура ТЕСТ_ВыполнитьНажатие(Кнопка)
ДатаНач = Дата(2009, 12, 31);
ДатаКон = Дата(2005, 1, 10);
Лет=0; Мес=0; Дн=0;
РазобратьРазностьДат(ДатаНач, ДатаКон, Лет, Мес, Дн);
ЛетС = ФормаМножественногоЧисла("год","года","лет",Лет);
МесС = ФормаМножественногоЧисла("месяц","месяца","месяцев",Мес);
ДнС = ФормаМножественногоЧисла("день","дня","дней",Дн);
Сообщить(?(Лет>0,Строка(Лет)+" "+ЛетС,"")+" "+?(Мес>0,Строка(Мес)+" "+МесС,"")+" "+Строка(дн)+" "+ДнС);
// Результат будет : 4 года 11 месяцев 21 день
КонецПроцедуры
// Получить разность дат
Процедура РазобратьРазностьДат(Дата1, Дата2, Лет = 0, Месяцев = 0, Дней = 0)
Лет = 0;
Месяцев = 0;
Дней = 0;
Если Дата1 > Дата2 Тогда
ВременнаяДата = Дата1;
Если День(ВременнаяДата) < День(Дата2) Тогда
Дней = (ВременнаяДата - ДобавитьМесяц(ВременнаяДата,-1))/86400;
ВременнаяДата = ДобавитьМесяц(ВременнаяДата,-1);
КонецЕсли;
Если Месяц(ВременнаяДата) < Месяц(Дата2) Тогда
ВременнаяДата = ДобавитьМесяц(ВременнаяДата,-12);
Месяцев = 12;
КонецЕсли;
Лет = Макс( Год(ВременнаяДата) - Год(Дата2), 0);
Месяцев = Макс(Месяцев + Месяц(ВременнаяДата) - Месяц(Дата2), 0);
Дней = Макс(Дней + День(ВременнаяДата) - День(Дата2), 0);
// скорректируем отображаемое значение, если ""вмешалось"" разное количество дней в месяцах
Если Дата2 <> (ДобавитьМесяц(Дата1,-Лет * 12-Месяцев)-Дней * 86400) Тогда
Дней = Дней + (День(КонецМесяца(Дата2)) - День(НачалоМесяца(Дата2))) - (День(КонецМесяца(ДобавитьМесяц(Дата1,-1))) - День(НачалоМесяца(ДобавитьМесяц(Дата1,-1))));
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Сформировать множественное число
Функция ФормаМножественногоЧисла(Слово1, Слово2, Слово3, Знач ЦелоеЧисло)
// Изменим знак целого числа, иначе отрицательные числа будут неправильно преобразовываться
Если ЦелоеЧисло < 0 Тогда
ЦелоеЧисло = -1 * ЦелоеЧисло;
КонецЕсли;
Если ЦелоеЧисло <> Цел(ЦелоеЧисло) Тогда
// для нецелых чисел - всегда вторая форма
Возврат Слово2;
КонецЕсли;
// остаток
Остаток = ЦелоеЧисло%10;
Если (ЦелоеЧисло >10) И (ЦелоеЧисло<20) Тогда
// для второго десятка - всегда третья форма
Возврат Слово3;
ИначеЕсли Остаток=1 Тогда
Возврат Слово1;
ИначеЕсли (Остаток>1) И (Остаток<5) Тогда
Возврат Слово2;
Иначе
Возврат Слово3;
КонецЕсли;
КонецФункции
Код 1C v 8.х
// Процедура вычисляет количество лет, месяцев и дней между двумя датами
//
// Параметры
// Дата1 – дата, первая дата (более поздняя, часто текущая, стаж определяется по состоянию на эту дату)
// Дата2 – дата, вторая дата (ранняя дата, с нее начинается ""течение"" стажа)
// Лет – Число, в этот параметр будет записано кол-во лет между двумя датами (Дата1-Дата2)
// Месяцев – Число, в этот параметр будет записано кол-во месяцев между двумя датами (Дата1-Дата2)
// Дней – Число, в этот параметр будет записано кол-во дней между двумя датами (Дата1-Дата2)
//
Процедура РазобратьРазностьДат(Дата1, Дата2, Лет = 0, Месяцев = 0, Дней = 0) Экспорт
Лет = 0;
Месяцев = 0;
Дней = 0;
Если Дата1 > Дата2 Тогда
ВременнаяДата = Дата1;
Если День(ВременнаяДата) < День(Дата2) Тогда
Дней = (ВременнаяДата - ДобавитьМесяц(ВременнаяДата,-1))/86400;
ВременнаяДата = ДобавитьМесяц(ВременнаяДата,-1);
КонецЕсли;
Если Месяц(ВременнаяДата) < Месяц(Дата2) Тогда
ВременнаяДата = ДобавитьМесяц(ВременнаяДата,-12);
Месяцев = 12;
КонецЕсли;
Лет = Макс( Год(ВременнаяДата) - Год(Дата2), 0);
Месяцев = Макс(Месяцев + Месяц(ВременнаяДата) - Месяц(Дата2), 0);
Дней = Макс(Дней + День(ВременнаяДата) - День(Дата2), 0);
// скорректируем отображаемое значение, если ""вмешалось"" разное количество дней в месяцах
Если Дата2 <> (ДобавитьМесяц(Дата1,-Лет * 12-Месяцев)-Дней * 86400) Тогда
Дней = Дней + (День(КонецМесяца(Дата2)) - День(НачалоМесяца(Дата2))) - (День(КонецМесяца(ДобавитьМесяц(Дата1,-1))) - День(НачалоМесяца(ДобавитьМесяц(Дата1,-1))));
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Вычисление периодов в формате ГГММДД. Вычисление дат по формуле Дата + ГГММДД.
Примечание: Даты передаем в виде 'ДД.ММ.ГГГГ', периоды - "ГГ-ММ-ДД".
Пользуйтесь.
arithmometr
Код 1C v 7.x
//********************************************************
//Назначение: преобразует строку в число путем преобразования каждого символа
//по правилам преобразования типов
// <стр> - строка;
//
//Примечание:
//
Функция зпГлСтрокуВЧисло(стр) Экспорт
стр1 = СокрЛП(стр);
Чис1 = "";
Для х = 1 По СтрДлина(стр1) Цикл
Чис1 = Чис1 + Число(Сред(стр1,х,1));
КонецЦикла;
Чис = Число(Чис1);
Возврат Чис;
КонецФункции // зпГлСтрокуВЧисло(стр)
//********************************************************
// Функция зпГлВычислитьСрок(Аргум1,Аргум2="",Парам=777)
// <Аргум1> - Дата1 или Срок1
// <Аргум2> - Дата2 или Срок2
// <Срок> - Период в формате ГГ-ММ-ДД
// Параметры: '0' - ЗнВозврата = Дата2-Дата1 - вичислить период между датами в формате ГГ-ММ-ДД
// '-1' - ЗнВозврата = Дата1-Срок - вычесть период
// '1' - ЗнВозврата = Дата1+Срок - добавить период
// Иначе ЗнВозврата = Правильный срок
// 'П' - ЗнВозврата = Правильный срок прописью
// 'К' - ЗнВозврата = Правильный срок прописью краткий формат
// '+' - ЗнВозврата = Срок1+Срок2 - сложить периоды
//////// '-' - ЗнВозврата = Срок1-Срок2 - вычесть периоды
//
// Примечание: Ст.241-1 КЗоТ Украины
//
Функция зпГлВычислитьСрок(Аргум1,Аргум2="",Парам="") Экспорт
Перем ЗнВозврата;
Если (Парам=0) Тогда
Дата1 = Мин(Дата(Аргум1),Дата(Аргум2));
Дата2 = Макс(Дата(Аргум1),Дата(Аргум2));
Мес = (ДатаГод(Дата2) - ДатаГод(Дата1))* 12 + (ДатаМесяц(Дата2) - ДатаМесяц(Дата1));
Дни = ДатаЧисло(Дата2) - ДатаЧисло(Дата1);
Если (Дни < 0) Тогда
Мес = Мес - 1;
Дни = Дни + ДатаЧисло(КонМесяца(Дата1));
КонецЕсли;
Если (Дни >= ДатаЧисло(КонМесяца(Дата2))) и (Дата2 = КонМесяца(Дата2)) Тогда
Мес = Мес + 1;
Дни = 0;
КонецЕсли;
Лет = Цел(Мес/12);
Мес = Мес - Лет* 12;
ЗнВозврата = Формат(Лет,"Ч(0)2.0")+"-"+Формат(Мес,"Ч(0)2.0")+"-"+Формат(Дни,"Ч(0)2.0");
ИначеЕсли (Число(Парам)*Число(Парам)=1) Тогда
Дата1 = Дата(Аргум1);
Аргум2 = зпГлВычислитьСрок(Аргум2);
Срок = Аргум2;
Мес = Число(Лев(Срок,2))* 12 + Число(Сред(Срок,4,2));
Дни = Число(Прав(Срок,2));
Дата2 = ДобавитьМесяц(Дата1,Парам*Мес);
Если (Дата1 = КонМесяца(Дата1)) Тогда
Дни = Мин(ДатаЧисло(КонМесяца(Дата2)) - 1, Дни);
ИначеЕсли (Дни >= ДатаЧисло(КонМесяца(Дата2))*((1-Парам)/2) - Парам*ДатаЧисло(Дата2)) Тогда
Дни = Мин(ДатаЧисло(КонМесяца(ДобавитьМесяц(Дата2,1))) - 1, Дни);
КонецЕсли;
ЗнВозврата = Дата2 + Парам*Дни;
Иначе
Если (Найти(Парам, "+") > 0) Тогда
Срок1 = зпГлСтрокуВЧисло(СтрЗаменить(Аргум1+".","-",""))/10;
Срок2 = зпГлСтрокуВЧисло(СтрЗаменить(Аргум2+".","-",""))/10;
Дни = Срок1%100 + Срок2%100;
Мес = Цел((Срок1%10000 + Срок2%10000 - Дни)/1000);
Лет = Цел(Срок1/10000) + Цел(Срок2/10000);
Мес = Мес + Цел(Дни/30);
Дни = Дни%30;
Лет = Лет + Цел(Мес/12);
Мес = Мес%12;
Иначе
Срок = зпГлСтрокуВЧисло(СтрЗаменить(Аргум1+".","-",""))/10;
Мес = Цел(Срок/100) - Цел(Срок/10000)*(100-12);
Дни = Мин(Срок - Цел(Срок/100)* 100, 30);
Лет = Цел(Мес/12);
Мес = Мес - Лет* 12;
КонецЕсли;
Если (Найти(Парам, "П") > 0) Тогда
ЗнВозврата = "років "+Лет+", місяців "+Мес+", днів "+Дни;
ИначеЕсли (Найти(Парам, "К") > 0) Тогда
ЗнВозврата = ""+Лет+"р."+Мес+"м."+Дни+"д.";
Иначе
ЗнВозврата = Формат(Лет,"Ч(0)2.0")+"-"+Формат(Мес,"Ч(0)2.0")+"-"+Формат(Дни,"Ч(0)2.0");
КонецЕсли;
КонецЕсли;
Возврат ЗнВозврата;
КонецФункции