IE 2016

Опять даты или "пятая нога" для стандартной платформы.

Опубликовал dusha0020 в раздел Программирование - Универсальные функции

Функции для работы с датами, которые почему-то забыли перенести из языка запросов в язык 1С.

С недавних пор в свои проекты я начал добавлять общий модуль для работы с датами. Не то чтобы без него было никак не обойтись, но с ним стало удобнее. Тот кто танцевал с бубном вокруг операций с датами на 8-й платформе меня, надеюсь, понимает.

Раскладывание дат по частям, а потом сборка после обработки напильником меня, признаться, не сильно утомляла, до тех пор пока не понадобилось в больших количествах складывать даты и время, находить разности и проверять настали ли заветные моменты. Стал писать запросы, а потом, когда сложность запросов превысила мои скромные способности взял и перенес две безусловно полезные функции языка запросов в прикладной функционал обычного языка. И, признаться, сразу полегчало.

ДОБАВИТЬКДАТЕ и РАЗНОСТЬДАТ по какой-то неведомой для меня причине забыли включить в обычный язык, то ли по недосмотру, то ли для того, чтобы побыстрее заставить переучиться на новый язык запросов. И хотя с момента рождения 8-ки минуло уже уйма лет (в минутах и секундах тоже можно узнать:) адекватная работа с датами так и осталась уделом запросов.

Я не хочу критиковать разработчиков платформы, и не хочу косить стартмани за добрые дела поэтому просто выкладываю содержимое своего стандартного модуля, который я традиционно называю РаботаСДатами. Клиент-серверные настройки модуля за вами, надеюсь только, что все помнят про то, что запросы на стороне клиента не доступны. У меня как правило он строго на сервере. Заветные 10 000 знаков в статье мне тоже не очень то нужны поэтому к делу (или к телу модуля):

Функция РазностьДат(НачальнаяДата,КонечнаяДата,Размерность) Экспорт
   Запрос = Новый ("Запрос");
   Если ВРег(Размерность) = "СЕКУНДА" Тогда
	   Запрос.Текст = 
	   "ВЫБРАТЬ
	   |	РАЗНОСТЬДАТ(&НачальнаяДата, &КонечнаяДата, МИНУТА)*60 +
	   |	(СЕКУНДА(&КонечнаяДата) - СЕКУНДА(&НачальнаяДата)) КАК Разность";
   Иначе
	   Запрос.Текст = 
	   "ВЫБРАТЬ
	   |	РАЗНОСТЬДАТ(&НачальнаяДата, &КонечнаяДата, " + Размерность + ") КАК Разность";
   КонецЕсли;
   Запрос.УстановитьПараметр("НачальнаяДата",НачальнаяДата);
   Запрос.УстановитьПараметр("КонечнаяДата",КонечнаяДата);
   Возврат Запрос.Выполнить().Выгрузить()[0].Разность;
КонецФункции

Функция ДобавитьКДате(НачальнаяДата,Количество,Размерность) Экспорт
   Запрос = Новый ("Запрос");
   Запрос.Текст = 
   "ВЫБРАТЬ
   |	ДОБАВИТЬКДАТЕ(&НачальнаяДата, " + Размерность + ",&Количество) КАК НоваяДата";
   Запрос.УстановитьПараметр("НачальнаяДата",НачальнаяДата);
   Запрос.УстановитьПараметр("Количество",Количество);
   Возврат Запрос.Выполнить().Выгрузить()[0].НоваяДата;
КонецФункции

Функция ДатаВЕдиницыВремени(НужнаяДата, Размерность) Экспорт
   Запрос = Новый ("Запрос");
   Если НЕ ВРег(Размерность) = "СЕКУНДА" Тогда
	   Запрос.Текст = 
	   "ВЫБРАТЬ
	   |	РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1,1,1,0,0,0), &КонечнаяДата, " + Размерность + ") КАК ДатаЧислом";
   Иначе
	   Запрос.Текст = 
	   "ВЫБРАТЬ
	   |	РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1,1,1,0,0,0), НАЧАЛОПЕРИОДА(&КонечнаяДата,МЕСЯЦ), МИНУТА)*60 + 
	   |    РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&КонечнаяДата,МЕСЯЦ), &КонечнаяДата, " + Размерность + ") КАК ДатаЧислом";
   КонецЕсли;
   
   Запрос.УстановитьПараметр("КонечнаяДата",НужнаяДата);
   Возврат Запрос.Выполнить().Выгрузить()[0].ДатаЧислом;
КонецФункции

Функция ЕдиницыВремениВДату(Количество,Размерность) Экспорт
	Запрос = Новый ("Запрос");
	Если ВРег(Размерность) = "СЕКУНДА" Тогда
	   Запрос.Текст = 
	   "ВЫБРАТЬ
	   |	ДОБАВИТЬКДАТЕ(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), МИНУТА,&КоличествоМ), " + Размерность + ", &КоличествоС) КАК НоваяДата";
	   КоличествоМ = Цел(Количество/60);
	   Запрос.УстановитьПараметр("КоличествоМ",КоличествоМ);
	   Запрос.УстановитьПараметр("КоличествоС",Количество - КоличествоМ*60);
	Иначе
		Запрос.Текст = 
	   "ВЫБРАТЬ
	   |	ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), " + Размерность + ",&Количество) КАК НоваяДата";
	   Запрос.УстановитьПараметр("Количество",Количество);
   КонецЕсли;
   Попытка
    	Возврат Запрос.Выполнить().Выгрузить()[0].НоваяДата;
	Исключение
		Возврат Дата(1,1,1,0,0,0);
	КонецПопытки;	
КонецФункции

Функция СуммаДатЧислом(Дата1, Дата2, Размерность) Экспорт
   Возврат ДатаВЕдиницыВремени(Дата1,Размерность) + ДатаВЕдиницыВремени(Дата2, Размерность);
КонецФункции

Функция СуммаДатДатой(Дата1,Дата2) Экспорт
	СуммаЧислом = СуммаДатЧислом(Дата1,Дата2,"СЕКУНДА");
	Возврат ЕдиницыВремениВДату(СуммаЧислом,"СЕКУНДА");
КонецФункции

Теперь немного пояснений и все. Потерпите еще пару минут. 

По назначению функций я думаю все понятно, но если нет прошу писать в комменты или личку. Размерность времени стандартная для запросов: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ и ГОД

По немного странному виду функций. Дело в том, что при обработке дат в размерности СЕКУНДА выяснилось, что ядро исполнителя запросов переполняется когда секунд становится немножко больше чем дофига. Пришлось менять основные отрезки на минутную размерность, добавляя потом секундные хвостики. А то иначе 1С пишет много страшных букв, призывая даже SQL в оправдание своей беспомощности перед столь грандиозным количеством разрядов.

А еще есть один интересный эффект, связанный со сложением дат. Внезапно (а как же еще) выяснилось, что 1С не знает, что бывают даты больше 4000 года от Р.Х. Ни в секундах, ни в минутах, ни даже в годах пояснить ему (или ей... я не знаю какого у Вас 1С рода) феномен бесконечности времени и пространства не удалось, поэтому если уж Вы начнете складывать что-то выходящее суммой за рамки то получите 01.01.01 00:00:00. Не обижайтесь и не расстраивайтесь, а лучше представьте, что когда нибудь спустя почти 2000 лет ученые будущего найдут винтажную систему учета 1С и вдруг выяснят, что 4000 годом заканчивается ее календарь и картина мира. В мире восцарится шок и паника - "Древние мудрецы предсказали конец света в 4000 году! Спасайтесь кто может!"Laughing

Вот такие любопытные параллели с 2012 годом, когда закончился календарь майя, заложили создатели 1С в свое детище. Может быть всего лишь 1986 лет спуся мир снова сойдет с ума от зловещих предсказаний господина Нуралиева?

Для желающих обязательно что-нибудь скачать и одарить меня $m набросал обработку-демонстратор возможностей. Извините, только управляемая форма.

Ну шутки шутками, а на этом прощаюсь и желаю всем хороших и интересных разработок.

Файлы

Наименование Файл Версия Размер Кол. Скачив.
DemoDates.epf
.epf 8,17Kb
21.10.14
14
.epf 8,17Kb 14 Скачать

См. также

Лучшие комментарии

12. ildarovich 24.10.2014 02:54
(0) Вот навскидку ДобавитьКДате
Функция ДобавитьКДате(НачальнаяДата, Количество, Размерность) Экспорт
	Шаг = Новый Структура("Год, Квартал, Месяц, Неделя, День, Час, Минута, Секунда", 12, 3, 1, -604800, -86400, -3600, -60, -1);
	Возврат ?(Шаг[Размерность] > 0, ДобавитьМесяц(НачальнаяДата, Количество * Шаг[Размерность]), НачальнаяДата - Количество * Шаг[Размерность])
КонецФункции
Структура "Шаг" - вещь постоянная. Ее можно и вне функции инициализировать для повышения быстродействия.
Насчет разности дат нужно еще подумать.
Ответили: (16)
# Ответить
1. МихаилМ 21.10.2014 12:55
использование для подобных мелко вычислительных задач субд - вандализм.
все эти методы пишутся без использования запросов.
Ответили: (2) (3) (7)
# Ответить
27. ildarovich 24.10.2014 23:02
(10) Rustig, в приведенном коде явная избыточность, так как игнорируется наличие очевидной закономерности: квартал - это номер тройки месяцев, то есть целое от деления номера месяца на три. В итоге лучше (как мне кажется) писать так
Функция ПолучитьКвартал(ДатаВступления) Экспорт  
    
    Если Не ЗначениеЗаполнено(ДатаВступления) Тогда
        Возврат Неопределено;
    КонецЕсли;
    
    НомерМесяца = Месяц(ДатаВступления) - 1;
              
    Квартал = Цел(НомерМесяца / 3);

    Возврат Квартал;
    
КонецФункции
...Показать Скрыть


Ну а я бы сразу сделал подстановку
Функция ПолучитьКвартал(ДатаВступления) Экспорт  
    Возврат ?(ЗначениеЗаполнено(ДатаВступления), Цел((Месяц(ДатаВступления) - 1) / 3), Неопределено)
КонецФункции
# Ответить

Комментарии

1. МихаилМ 21.10.2014 12:55
использование для подобных мелко вычислительных задач субд - вандализм.
все эти методы пишутся без использования запросов.
Ответили: (2) (3) (7)
# Ответить
2. dusha0020 21.10.2014 13:57
(1) МихаилМ, Возразить нечего. Ну кроме того, что никто еще подобные функции не написал и не сравнил с этими по простоте реализации, точности вычислений и времени работы. Думаете у меня такой мысли не было?:)
Ответили: (3)
+ 2 [ CITRUM; ojiojiowka; ]
# Ответить
3. kapustinag 22.10.2014 10:46
(1) МихаилМ, (2) dusha0020,
Да, появилась точно такая же мысль при первом прочтении текста модуля. Потому что - совершенно точно - на стороне СУБД, например, разность дат вычисляется в конечном итоге какой-нибудь функцией на Си или ассемблере.

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

Поэтому, считаю, вполне нормальный вариант, если применять с умом.
# Ответить
4. DAnry 22.10.2014 14:58
Поддерживаю автора. Мне тоже кажется, что отсутствие подобных функций в "обычном" языке 1С мягко говоря "оплошность" разработчиков. С критикой не согласен. Представленные функции предназначены не для пользователей, а для программиста, т.е. человека думающего. Ну и никто не заставляет их использовать, можно написать свои.
Ответили: (5)
# Ответить
5. МихаилМ 23.10.2014 09:38
(4) DAnry,

программисты 1с - не программисты. т.к. не думающие. естественно в общей массе, усредненно.

но в долгую полемику в этой ветке вступать не хочется. тк получается флуд.
# Ответить
6. PiccaHut001 23.10.2014 18:14
Дело в том, что при обработке дат в размерности СЕКУНДА выяснилось, что ядро исполнителя запросов переполняется когда секунд становится немножко больше чем дофига
- другого мы от 1С и не ожидали.
# Ответить
7. PiccaHut001 23.10.2014 18:16
(1) МихаилМ, вандализм, это когда криворукие студенты "погромисты" платформы "забыли" добавить эти функции во встроенный язык. Всё делают наполовину. Сколько процессорного времени можно было бы сэкономить...
Ответили: (21)
− 3 [ Evil Beaver; ildarovich; awk; ]
# Ответить
8. Fragster 23.10.2014 22:09
Спорно. Например следует учесть, что в языке запросов просто сравнивается соответствующие "левые" части даты в формате ГГГГММДДччммсс, соответственно, можно не дергать сервер СУБД по сети, а просто сравнить Формат(Дата1,) и Формат(Дата1,) подставив соответствующий формат. Или Кгод*Год(Дата1) + Кмесяц*Месяц(Дата1) + Кдень*День(Дата1)... - .... Задержка будет СИЛЬНО меньше.


Также если нужно сравнить, допустим, "количество полных месяцев абонентской платы, которая начисляется в соответствующее число месяца", то всё усложняется.
# Ответить
9. awk 23.10.2014 22:15
Функция РазностьДат(НачальнаяДата,КонечнаяДата,Размерность) Экспорт
   Запрос = Новый ("Запрос");
   Если ВРег(Размерность) = "СЕКУНДА" Тогда
       Запрос.Текст = 
       "ВЫБРАТЬ
       |    РАЗНОСТЬДАТ(&НачальнаяДата, &КонечнаяДата, МИНУТА)*60 +
       |    (СЕКУНДА(&КонечнаяДата) - СЕКУНДА(&НачальнаяДата)) КАК Разность";
   Иначе
       Запрос.Текст = 
       "ВЫБРАТЬ
       |    РАЗНОСТЬДАТ(&НачальнаяДата, &КонечнаяДата, " + Размерность + ") КАК Разность";
   КонецЕсли;
   Запрос.УстановитьПараметр("НачальнаяДата",НачальнаяДата);
   Запрос.УстановитьПараметр("КонечнаяДата",КонечнаяДата);
   Возврат Запрос.Выполнить().Выгрузить()[0].Разность;
КонецФункции
...Показать Скрыть


Первое приближение

Функция РазностьДат(НачальнаяДата,КонечнаяДата,Размерность) Экспорт
   Если ВРег(Размерность) = "СЕКУНДА" Тогда
       Возврат КонечнаяДата - НачальнаяДата;
   ИначеЕсли ВРег(Размерность) = "МИНУТА" Тогда
       Возврат ЦЕЛ((КонечнаяДата - НачальнаяДата) /60);
   ИначеЕсли ВРег(Размерность) = "ЧАС" Тогда
       Возврат ЦЕЛ((КонечнаяДата - НачальнаяДата )/3600);
   ИначеЕсли ВРег(Размерность) = "ДЕНЬ" Тогда
       Возврат ЦЕЛ((КонечнаяДата - НачальнаяДата) /86400);
   ИначеЕсли ВРег(Размерность) = "НЕДЕЛЯ" Тогда
       Возврат ЦЕЛ((КонечнаяДата - НачальнаяДата) /(86400*7));
   ИначеЕсли ВРег(Размерность) = "ДЕКАДА" Тогда
       Возврат ЦЕЛ((КонечнаяДата - НачальнаяДата) /(86400*10));
   ИначеЕсли ВРег(Размерность) = "МЕСЯЦ" Тогда
       Возврат ГОД(КонечнаяДата)*12 + Месяц(КонечнаяДата) - ГОД(НачальнаяДата)*12 - Месяц(НачальнаяДата);
   ИначеЕсли ВРег(Размерность) = "КВРТАЛ" Тогда
       Возврат ЦЕЛ((ГОД(КонечнаяДата)*12 + Месяц(КонечнаяДата) - ГОД(НачальнаяДата)*12 - Месяц(НачальнаяДата))/3);
   ИначеЕсли ВРег(Размерность) = "ПОЛУГОДИЕ" Тогда
       Возврат ЦЕЛ((ГОД(КонечнаяДата)*12 + Месяц(КонечнаяДата) - ГОД(НачальнаяДата)*12 - Месяц(НачальнаяДата))/6);
   ИначеЕсли ВРег(Размерность) = "ГОД" Тогда
       Возврат ГОД(КонечнаяДата) - ГОД(НачальнаяДата);
   Иначе
       ВызватьИсключение "Не правильная размерность";
   КонецЕсли;
КонецФункции
...Показать Скрыть
+ 3 [ evillit; sashocq; monkbest; ]
# Ответить
10. Rustig 23.10.2014 23:40
(0) у меня тоже нашлись разработки методов анализа дат, отдельный модуль под это отвел, выкладываю самое адекватное из найденного :)

Функция ПолучитьКвартал(ДатаВступления) Экспорт  
	
	Если Не ЗначениеЗаполнено(ДатаВступления) Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	НомерМесяца = Число(Формат(ДатаВступления, "ДФ=М"));
	Если НомерМесяца = 1 Или НомерМесяца = 2 Или НомерМесяца = 3 Тогда
		Квартал = 1;
	ИначеЕсли НомерМесяца = 4 Или НомерМесяца = 5 Или НомерМесяца = 6 Тогда
		Квартал = 2;
	ИначеЕсли НомерМесяца = 7 Или НомерМесяца = 8 Или НомерМесяца = 9 Тогда
		Квартал = 3;
	ИначеЕсли НомерМесяца = 10 Или НомерМесяца = 11 Или НомерМесяца = 12 Тогда
		Квартал = 4;
	КонецЕсли;  		
	
	Возврат Квартал;
	
КонецФункции
...Показать Скрыть
Ответили: (16) (27)
# Ответить
11. Rustig 23.10.2014 23:44
(0) я однажды задумался почему же разработчики не прописали методы работы с датами, так вот , мне кажется их настолько много, что под каждую задачу разработчик сам напишет алгоритм. помню в универе целая книжка была по программистским задачам: отдельная глава на разработку алгоритмов для строк, отдельная глава для разработки алгоритмов для дат и т.д.
всем не угодишь
Ответили: (19)
+ 2 [ monkbest; awk; ]
# Ответить
12. ildarovich 24.10.2014 02:54
(0) Вот навскидку ДобавитьКДате
Функция ДобавитьКДате(НачальнаяДата, Количество, Размерность) Экспорт
	Шаг = Новый Структура("Год, Квартал, Месяц, Неделя, День, Час, Минута, Секунда", 12, 3, 1, -604800, -86400, -3600, -60, -1);
	Возврат ?(Шаг[Размерность] > 0, ДобавитьМесяц(НачальнаяДата, Количество * Шаг[Размерность]), НачальнаяДата - Количество * Шаг[Размерность])
КонецФункции
Структура "Шаг" - вещь постоянная. Ее можно и вне функции инициализировать для повышения быстродействия.
Насчет разности дат нужно еще подумать.
Ответили: (16)
# Ответить
13. zqzq 24.10.2014 08:36
Переполнение разрядности секунд и 4000 год - это баг не 1С, а MS SQL. Ещё один аргумент, чтобы эти функции переписать с запросов на встроенный язык 1С.
# Ответить
14. ildarovich 24.10.2014 09:57
(0) Вот РазностьДат
Функция РазностьДат(Дата1, Дата2, Период) Экспорт
	Шаг = Новый Структура("Год, Квартал, Месяц, Неделя, День, Час, Минута, Секунда", 1, 4, 12, -604800, -86400, -3600, -60, -1);
	Ход = Новый Структура("Год, Квартал, Месяц", 0, Цел((Месяц(Дата2) - 1) / 3) - Цел((Месяц(Дата1) - 1) / 3), Месяц(Дата2)- Месяц(Дата1));
	Возврат ?(Шаг[Период] > 0, (Год(Дата2) - Год(Дата1)) * Шаг[Период] + Ход[Период], Цел(('00010101' - Дата2) / Шаг[Период]) - Цел(('00010101' - Дата1) / Шаг[Период]))
КонецФункции
...Показать Скрыть
На первый взгляд, работает. Бонусом является размерность "Неделя". Нужно еще попытаться отрефакторить - менее громоздко переписать (вместо структуры Ход и части Шаг Если или ? применить). Быстродействие сравнить.
Вот вариант после рефакторинга
Функция РазностьДат(Дата1, Дата2, Период) Экспорт
	Если ВРег(Период) = "ГОД" Тогда
		Возврат Год(Дата2) - Год(Дата1)
	ИначеЕсли ВРег(Период) = "КВАРТАЛ" Тогда
		Возврат (Год(Дата2) - Год(Дата1)) * 4 + Цел((Месяц(Дата2) - 1) / 3) - Цел((Месяц(Дата1) - 1) / 3)
	ИначеЕсли ВРег(Период) = "МЕСЯЦ" Тогда
		Возврат (Год(Дата2) - Год(Дата1)) * 12 + Месяц(Дата2) - Месяц(Дата1)
	Иначе
		Шаг = Новый Структура("Неделя, День, Час, Минута, Секунда", 604800, 86400, 3600, 60, 1);
		Возврат Цел((Дата2 - '00010101') / Шаг[Период]) - Цел((Дата1 - '00010101') / Шаг[Период])
	КонецЕсли
КонецФункции
...Показать Скрыть
Протестировал быстродействие. Тысяча вызовов выполняется для ДобавитьКДате и РазностьДат запросом за 2,90 и 3,04 секунды соответственно. То же самое приведенным кодом за 0,275 и 0,254 секунды соответственно. То есть выигрыш в 10 - 12 раз!

Когда тестировал на совпадение результатов, обратил внимание, что запрос часто вываливался с ошибкой, не переваривая больших значений секунд, минут, часов, и так далее. Код эти значения обрабатывал.

Оказалось, существует еще более короткий и только чуть более медленный вариант. Вот он:
Функция РазностьДат(Дата1, Дата2, Период) Экспорт
	Шаг = Новый Структура("Год, Квартал, Месяц, Неделя, День, Час, Минута, Секунда", 12, 3, 1, -604800, -86400, -3600, -60, -1);
	Возврат Цел(?(Шаг[Период] > 0, Год(Дата2) * 12 + Месяц(Дата2) - 1, '00010101' - Дата2) / Шаг[Период]) 
		  - Цел(?(Шаг[Период] > 0, Год(Дата1) * 12 + Месяц(Дата1) - 1, '00010101' - Дата1) / Шаг[Период])
КонецФункции
...Показать Скрыть
Теперь 0,275 и 0,322 секунды.
А если вынести инициализацию структуры Шаг из функции, то получается 0,1212 и 0,1639. То есть итоговое ускорение в 20-25 раз.
+ 1 [ kote; ]
# Ответить
15. ildarovich 24.10.2014 09:59
А зачем остальные функции, кроме РазностьДат и ДобавитьКДате, я не понял.
# Ответить
16. PiccaHut001 24.10.2014 10:14
(10) Rustig, браво, это шедевр. Абсолютно всё понятно, не то что творения (12) очередных рукоблудов виртуозов. В ваших разработках случайно нет таблицы с названиями месяцев по русски, например таб[1]= "январь"; таб[2]= "февраль"; ... ? Выложите, пожалуйста, если есть.
Ответили: (17) (26)
# Ответить
17. awk 24.10.2014 10:59
(16) PiccaHut001, Сергей конечно не образец форматирования кода, но крайне сильный алгоритмист. А некоторые и F=m*a или F(1-2)=-F(2-1) не понимают.
# Ответить
18. burlakov 24.10.2014 11:00
давно для себя похожие фишки сделал. реально помогают. особенно учитывая, что у нас на предприятии есть свои сутки, по которым оно живет. с 08:00:00 по 07:59:59, да еще могут ограничиваться концом декады, месяца, года. в декаде тоже не всегда 10 дней, в месяце может быть 2 декады... в общем свои извраты, но такой подход реально помогает.
# Ответить
19. awk 24.10.2014 11:01
(11) Rustig, Про "недопрограммистов", которые "забыли написать", может говорить только человек не написавший ни одного коммерческого приложения...
Ответили: (20)
# Ответить
20. PiccaHut001 24.10.2014 13:31
(19) awk, не обязательно быть поваром, чтобы на скверно приготовленный протухший Доширак сказать "*овно".
# Ответить
21. ildarovich 24.10.2014 14:12
(7) PiccaHut001, есть такое слово - "невежество", которое (здесь это совершенно очевидно для многих) вы этим постом демонстрируете, ничего не зная как устроена разработка в 1С.

Есть такой анекдот: бежит по лесу муравей - радуется. Говорит: там на поляне звери слона пинали - я тоже два раза пнул. Не смешите людей - не будьте в роли этого муравья..
Ответили: (22)
+ 1 [ dj_serega; ]
# Ответить
22. PiccaHut001 24.10.2014 15:28
(21) ildarovich, мне всё равно как у "них" устроена разработка, о чём можна говорить, если на сайте 1с висят нерассмотренные ошибки с 2012 года. Т.е. письмо приняли, номер присвоили и всё. Тестировщикам "влом" зайти в 1С и воспроизвести ошибку. И я должнен на это молиться? Или постить свой очереднойовнокод мегашедевр в 200 символов без переносов строк, скобок и абзацев?
# Ответить
23. SemenovaMarinaV 24.10.2014 17:25
Очень полезно.
А как в запросе соединить ФИзЛицо.наменование+ФизЛицо.ДатаРождения
Ответили: (25)
# Ответить
24. SemenovaMarinaV 24.10.2014 17:26
А то замучалась
# Ответить
25. PiccaHut001 24.10.2014 18:07
(23) SemenovaMarinaV, в запросе можна, но очень очень гемморойно(спасибо 1С), лучше ячейке, где выводится, поставить тип шаблон и слепить там. Или в скд сделать вычисляемое поле.
# Ответить
26. ildarovich 24.10.2014 22:47
(16) PiccaHut001, таблица с названием месяцев по русски не потребуется, если знать, что
Формат(Дата(1, НомерМесяца, 1), "ДФ=MMММ")
возвращает как раз такие названия.
# Ответить
27. ildarovich 24.10.2014 23:02
(10) Rustig, в приведенном коде явная избыточность, так как игнорируется наличие очевидной закономерности: квартал - это номер тройки месяцев, то есть целое от деления номера месяца на три. В итоге лучше (как мне кажется) писать так
Функция ПолучитьКвартал(ДатаВступления) Экспорт  
    
    Если Не ЗначениеЗаполнено(ДатаВступления) Тогда
        Возврат Неопределено;
    КонецЕсли;
    
    НомерМесяца = Месяц(ДатаВступления) - 1;
              
    Квартал = Цел(НомерМесяца / 3);

    Возврат Квартал;
    
КонецФункции
...Показать Скрыть


Ну а я бы сразу сделал подстановку
Функция ПолучитьКвартал(ДатаВступления) Экспорт  
    Возврат ?(ЗначениеЗаполнено(ДатаВступления), Цел((Месяц(ДатаВступления) - 1) / 3), Неопределено)
КонецФункции
# Ответить
28. ildarovich 26.10.2014 11:00
Поставил статье плюс не только за привлечение внимание к теме и отличное оформление, но и за идею использовать приведенные функции языка запросов как эталонные для таких вычислений в коде. Без этого программирование разности дат может превратиться в отсебятину, не учитывающую множество нюансов работы с датами.
Например, все ли обращали внимание на то, что
РазностьДат('20131231235959', '20140101', "Год") = 1 или РазностьДат('20141026115959','20141026120000',"Час") = 1
А тем не менее, это так. И приведенные в комментариях (12) и (14) реализации это учитывают.
Найденные в процессе этого обсуждения решения приведены теперь также в статье Минимализмы.
# Ответить
29. webester 27.10.2014 04:11
Прошу прощения за тупой вопрос, видимо мне одному непонятно, чем же вас не устраивает вариант Дата2 - Дата1 с последующим анализом результата? Когда надо прибавить к дате какое то количество дней, или часов или еще чего почему нельзя использовать, что то вроде этого: Дата1 = Дата1 + 3 * 86400; На вид это элементарно, работает на клиенте, анализировать можно как угодно гибко и наверняка у вас какие то причины не использовать этот подход, но какие, никак не могу понять.
Ответили: (35)
+ 1 [ monkbest; ]
# Ответить
30. monkbest 27.10.2014 08:46
Свои 5 копеек.
Бред лазить с клиента на сервер, чтобы посчитать дни.
Встроенные функции не нужны, т.к. единственная засада в этих задачах это разность дат в месяцах, у неё есть разные алгоритмы решения, некоторые из них регламентированы трудовым кодексом.

Самый простой пример - сколько дней отпуска у человека осталось, если в месяц ему накапливается 2.33 дня, а период работы с 12.01.2010 по 18.11.2010?
Вот тут ни запрос, ни мат.формулы не помогут, тут надо анализировать в какую половину месяца попадает первая дата, в какую вторая.
Ответили: (32)
# Ответить
31. monkbest 27.10.2014 08:48
Еще пример - посчитать стаж. Вся хрень, в разном количестве дней в месяце, поэтому при подсчете в зависимости от алгоритма может быть +/- 1 день. И реально, у разных разработчиков почти всегда отличается результат при равных исходных данных!
# Ответить
32. PiccaHut001 27.10.2014 10:06
(30) monkbest,
Бред лазить с клиента на сервер, чтобы посчитать дни
Вы замеряли? У Вас тормозит?
Ответили: (33) (34)
# Ответить
33. monkbest 27.10.2014 10:19
(32) PiccaHut001, да тормозит:)
превосходство в 4 471 раз!!!
проверял, вот замеры:
# Ответить
34. monkbest 27.10.2014 10:23
(32) PiccaHut001,
усложняем задачу, разность в минутах, тут надо поделить на 60 и округлить
превосходство все равно огромное в 3 027 раз
Ответили: (36)
# Ответить
35. awk 27.10.2014 10:31
(29) webester, Можно. Так и делаю. Вопрос встает когда период добавления вариативен. Да и наглядность РазностьДат(А,Б, "день") выше ЦЕЛ((Б-А)/86400); Смотри антипаттерн "магические числа".
Ответили: (46)
# Ответить
36. PiccaHut001 27.10.2014 13:32
(34) monkbest, в случае "массовых" вычислений проще весь цикл вынести на сервер. Думаю, разница будет не такая существенная.
Ответили: (37) (48)
# Ответить
37. monkbest 27.10.2014 13:45
(36) PiccaHut001, массовость была использована для точного вычисления соотношения времени. В единичном вычислении соотношение остается прежним. Конечно, +/- микросекунда - никто не заметит, но если там 5000 строк кода и все они написаны в таком мягко говоря неоптимальном стиле?

Пусть документ заполняется обработкой за 2 секунды.
Путь в нем 1% кода станет таким ужасным.
Пусть вычисления сложные и мы не в 3000 раз, а всего в 1000 раз проигрываем
1,98сек + 0,02 * 1000 = 39,6 сек

а это уже не моргнул глазом, а успел выпить заранее налитый кофе :)
Ответили: (38)
# Ответить
38. awk 27.10.2014 14:48
(37) monkbest, Для "велосипедоизобретателей" см. сюда: http://algolist.manual.ru/misc/o_n.php
Ответили: (39)
# Ответить
39. monkbest 27.10.2014 15:40
(38) awk, посмотрел, спасибо, я в институте уже это слушал на лекциях. Это теория для оценки более сложных задач. Мне же требовалось человеку наглядно на "пальцах" показать, что код из статьи, как он говорит, "тормозит".
Так что не понимаю, к чему Вы меня отправили "читать мат.часть"
Ответили: (40)
# Ответить
40. awk 27.10.2014 16:00
(39) monkbest, На пальцах вы показали пальцы - не более... :))) Что мерили, зачем - непонятно.
Ответили: (41)
# Ответить
41. monkbest 27.10.2014 16:36
(40) awk, задача:
количественно сравнить производительность метода №1 и №2
решение:
выбираем критерий сравнения - время выполнения кода
пишем код, для точности выполняем код многократно
производим замер
результат:
получена количественная оценка двух методов, позволяющая их сравнить, берем соотношение оценок

Давай зачетку - пять

если Вы хотели, чтобы я написал пару "умных" формул в своих постах, то Вам к еврейским авторам учебников по высшей математике, они любят лить воду значками и буковками, чтобы обычным людям непонятно было. Чем непонятнее, тем умней - это не про меня
Ответили: (42)
# Ответить
42. awk 27.10.2014 17:22
(41) monkbest, Как говорил профессор Барилович: "Плохо. Двойка вам.".
Ответили: (43)
# Ответить
43. monkbest 27.10.2014 17:30
(42) awk, плохие педагоги ставят оценки, хорошие объясняю что не так и как надо было.
Вы же хороший?
Ответили: (44) (45)
# Ответить
44. awk 27.10.2014 17:48
(43) monkbest, Почитал бы по ссылке и понял сам. Ну раз вы ленивы привожу цитату:

алгоритм со временем O(n2) может работать значительно быстрее алгоритма O(n) при малых n... За счет того, что реальное количество операций первого алгоритма может быть n2 + 10n + 6, а второго - 1000000n + 5. Впрочем, второй алгоритм рано или поздно обгонит первый... n2 растет куда быстрее 1000000n.
Поэтому:
1. Замер твой показал, что алгоритм А работает быстрее алгоритма Б, на N входящих данных.
2. Что такое многократно? Больше чем до..уя или меньше чем до..уя? Что ты этим измеряешь? Статистическое отклонение задержек?
Ответили: (48)
# Ответить
45. awk 27.10.2014 17:52
(43) monkbest, В среде профессиональных юмористов, все анекдоты давно перенумерованы и в целях экономии времени ржут над цифрами... Когда же очередной поручик Ржевский входит и называет номер, то обычно получает пощечину от дам - за пошлость.
Ответили: (47)
+ 1 [ dj_serega; ]
# Ответить
46. webester 28.10.2014 14:57
(35)Нарисуй обертку, и будет тебе такая наглядность какая нужно.
# Ответить
47. ildarovich 28.10.2014 15:14
(45) awk, как говорится, Платон мне друг, но истина дороже: профессиональные юмористы ржут над числами, а не над цифрами.
+ 1 [ awk; ]
# Ответить
48. monkbest 30.10.2014 08:53
(44) awk, Вы думаете, что на одном вычислении соотношение будет другое? Нет, там будут микросекунды, но соотношение будет тем же.
наверное мы не понимаем друг друга. Я исходно считал не увеличение времени в секундах, а соотношение времени выполнения. В этом случае количество повторов не играет значение, количество повторов = количеству экспериментов, что снижает воздействие случайных событий (а они есть в работе компьютера) на результат.
Далее мне сказали, что нех внутри цикла вызывать сервер. Я в ответ попытался сказать (36), что данный код возможно в коде используется и один раз, и потери может и незаметны, но если кода много и весь остальной код хотя бы на 1% также ужасно написан, то результат будет плачевным.
Ответили: (49)
# Ответить
49. awk 30.10.2014 17:17
(48) monkbest, На результат влияет все: ресурсы, состав данных и т.д. Так что ваш многократный замер ничего не показывает. Изменились данные и ...
Ответили: (50)
# Ответить
50. monkbest 31.10.2014 08:26
(49) awk, ну Вам мой замер ничего не говорит. А мне говорит, что посчитать самому на клиенте - быстрее, чем обратиться к серверу, а с сервера к субд. Это и так было очевидно, просто я получил реальные цифры, чтобы не разводить демагогию.

собственно, если Вам мой эксперимент ни о чем не говорит, я ставлю под сомнение Ваше образование и квалификацию
Ответили: (51)
# Ответить
51. awk 31.10.2014 11:32
(50) monkbest, Да быдло-кодер я.. Даже среднего нет... А вы где и почем покупали, может я то же прикуплю?
# Ответить
52. dusha0020 31.10.2014 12:17
Ребята, извините, но мне не нравится тон и предмет текущего обсуждения. Ваши замечания я принял, удачные решения и мысли отметил. Спасибо большое всем за дискуссию. Но сейчас пошел какой-то троллинг. Я закрываю тему. Меряться понтами и профессионализмами прошу в личку или OFF. Прошу не обижаться. Еще раз повторяю - мне интересны и полезны все Ваши мысли и все выводы и советы, но до тех пор, пока они относятся к обсуждаемому вопросу.
+ 3 [ evillit; alexscamp; kote; ]
# Ответить
Внимание! За постинг в данном форуме $m не начисляются.
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл






IE 2016