Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Обычная тема Класс Периоды (наложения, вхождения периодов) (число прочтений - 4744 )
Kostya
Junior Member
**
Отсутствует



Сообщений: 62
Местоположение: Украина / Луцк
Зарегистрирован: 14. Декабря 2006
Пол: Мужской
Класс Периоды (наложения, вхождения периодов)
23. Января 2007 :: 17:44
Печать  
Код
Выбрать все
Функция ВхождениеДатыВПериод(НачПериода,КонПериода,ДатаВхождения) Экспорт;
	НачалоПериода=Дата(НачПериода);
	КонецПериода=Дата(КонПериода);
	ДатаВозможногоВхождения=Дата(ДатаВхождения);
	Если ПустоеЗначение(НачалоПериода)=0 Тогда //нельзя быть левее бесконечности слева
		Если (ДатаВозможногоВхождения<НачалоПериода) Тогда
			Возврат 0; //не входит
		КонецЕсли;
	КонецЕсли;
	Если ПустоеЗначение(КонецПериода)=0 Тогда //нельзя быть правее бесконечности справа
		Если (ДатаВозможногоВхождения>КонецПериода) Тогда
			Возврат 0; //не входит
		КонецЕсли;
	КонецЕсли;
	Возврат 1; //входит
КонецФункции

Функция ОбщийПериод(НачПериода1,КонПериода1,НачПериода2,КонПериода2) Экспорт;

	ИскомоеНачало=ПолучитьПустоеЗначение("Дата");
	ИскомыйКонец=ПолучитьПустоеЗначение("Дата");
	НачалоПериода1=Дата(НачПериода1);
	КонецПериода1=Дата(КонПериода1);
	НачалоПериода2=Дата(НачПериода2);
	КонецПериода2=Дата(КонПериода2);

	//обмен производится только в случае непустых значений
	Если ПустоеЗначение(НачалоПериода1)=0 Тогда
	Если ПустоеЗначение(КонецПериода1)=0 Тогда
	Если НачалоПериода1>КонецПериода1 Тогда
		Обмен=НачалоПериода1;
		НачалоПериода1=КонецПериода1;
		КонецПериода1=Обмен;
	КонецЕсли;
	КонецЕсли;
	КонецЕсли;

	Если ПустоеЗначение(НачалоПериода2)=0 Тогда
	Если ПустоеЗначение(КонецПериода2)=0 Тогда
	Если НачалоПериода2>КонецПериода2 Тогда
		Обмен=НачалоПериода2;
		НачалоПериода2=КонецПериода2;
		КонецПериода2=Обмен;
	КонецЕсли;
	КонецЕсли;
	КонецЕсли;

	СЗНачало=СоздатьОбъект("СписокЗначений");
	СЗКонец=СоздатьОбъект("СписокЗначений");

	Если ВхождениеДатыВПериод(НачалоПериода1,КонецПериода1,НачалоПериода2)=1 Тогда
		СЗНачало.ДобавитьЗначение(НачалоПериода2);
	КонецЕсли;
	Если ВхождениеДатыВПериод(НачалоПериода1,КонецПериода1,КонецПериода2)=1 Тогда
		СЗКонец.ДобавитьЗначение(КонецПериода2);
	КонецЕсли;
	Если ВхождениеДатыВПериод(НачалоПериода2,КонецПериода2,НачалоПериода1)=1 Тогда
		СЗНачало.ДобавитьЗначение(НачалоПериода1);
	КонецЕсли;
	Если ВхождениеДатыВПериод(НачалоПериода2,КонецПериода2,КонецПериода1)=1 Тогда
		СЗКонец.ДобавитьЗначение(КонецПериода1);
	КонецЕсли;

	Если СЗНачало.РазмерСписка()>0 Тогда
		СЗНачало.Сортировать(0); //берем самую левую точку
		ИскомоеНачало=СЗНачало.ПолучитьЗначение(1);
	КонецЕсли;

	Если СЗКонец.РазмерСписка()>0 Тогда
	    СЗКонец.Сортировать(1); //берем самую правую точку
		ИскомыйКонец=СЗКонец.ПолучитьЗначение(1);
	КонецЕсли;

	СЗ=СоздатьОбъект("СписокЗначений");
	СЗ.Установить("НачДата",ИскомоеНачало);
	СЗ.Установить("КонДата",ИскомыйКонец);

	Возврат СЗ;
КонецФункции

Функция ВхождениеПериодов(НачПериода1,КонПериода1,НачПериода2,КонПериода2) Экспорт;
	СЗ=ОбщийПериод(НачПериода1,КонПериода1,НачПериода2,КонПериода2);
	Если ПустоеЗначение(СЗ.Получить("НачДата"))=0 Тогда
		Возврат 1; //вхождение есть
	КонецЕсли;
	Если ПустоеЗначение(СЗ.Получить("КонДата"))=0 Тогда
		Возврат 1; //вхождение есть
	КонецЕсли;
Возврат 0;
КонецФункции

Функция ТекстовыйПериод(СЗ) Экспорт;
	Нач=СЗ.Получить("НачДата");
	Если ПустоеЗначение(Нач)=1 Тогда
		Нач="пусто";
	КонецЕсли;
	Кон=СЗ.Получить("КонДата");
	Если ПустоеЗначение(Кон)=1 Тогда
		Кон="пусто";
	КонецЕсли;
Возврат ""+Нач+" -> "+Кон;
КонецФункции

Процедура СообщитьПериод(СЗ) Экспорт;
 	Сообщить(ТекстовыйПериод(СЗ));
КонецПроцедуры
 


  

2b or not 2b = ff
Наверх
ICQ  
IP записан
 
Kostya
Junior Member
**
Отсутствует



Сообщений: 62
Местоположение: Украина / Луцк
Зарегистрирован: 14. Декабря 2006
Пол: Мужской
Re: Класс Периоды (наложения, вхождения периодов)
Ответ #1 - 23. Января 2007 :: 17:45
Печать  
Код
Выбрать все
Процедура Тесты() Экспорт;
//полное входение периода2 в период1.
Если ТекстовыйПериод(ОбщийПериод("01.01.06","28.02.06","15.01.06","20.01.06"))
="15.01.06 -> 20.01.06" Тогда
   Сообщить("Тест 1 пройден");
Иначе
   Сообщить("Тест 1 не пройден","!!!");
КонецЕсли;

//полное входение периода1 в период2.
Если ТекстовыйПериод(ОбщийПериод("15.01.06","20.01.06","01.01.06","28.02.06"))
="15.01.06 -> 20.01.06" Тогда
   Сообщить("Тест 2 пройден");
Иначе
   Сообщить("Тест 2 не пройден","!!!");
КонецЕсли;

//наложение периодов, где первый левее
Если ТекстовыйПериод(ОбщийПериод("01.01.06","28.02.06","15.01.06","15.05.06"))
="15.01.06 -> 28.02.06" Тогда
   Сообщить("Тест 3 пройден");
Иначе
   Сообщить("Тест 3 не пройден","!!!");
КонецЕсли;

//наложение периодов, где первый правее
Если ТекстовыйПериод(ОбщийПериод("15.01.06","15.05.06","01.01.06","28.02.06"))
="15.01.06 -> 28.02.06" Тогда
   Сообщить("Тест 4 пройден");
Иначе
   Сообщить("Тест 4 не пройден","!!!");
КонецЕсли;

//наложение периодов, где первый левее и даты местами поменяны
Если ТекстовыйПериод(ОбщийПериод("31.01.06","01.01.06","15.01.06","15.05.06"))
="15.01.06 -> 31.01.06" Тогда
   Сообщить("Тест 5 пройден");
Иначе
   Сообщить("Тест 5 не пройден","!!!");
КонецЕсли;

//наложение периодов, где первый правее и даты в нем местами поменяны
Если ТекстовыйПериод(ОбщийПериод("15.01.06","15.05.06","31.01.06","01.01.06"))
="15.01.06 -> 31.01.06" Тогда
   Сообщить("Тест 6 пройден");
Иначе
   Сообщить("Тест 6 не пройден","!!!");
КонецЕсли;

//периоды не пересекаются вообще
Если ТекстовыйПериод(ОбщийПериод("01.01.06","28.02.06","15.03.06","15.05.06"))
="пусто -> пусто" Тогда
   Сообщить("Тест 7 пройден");
Иначе
   Сообщить("Тест 7 не пройден","!!!");
КонецЕсли;

//наложение периодов, где период1 начинается из бесконечности
Если ТекстовыйПериод(ОбщийПериод("","30.01.06","15.01.06","15.05.06"))
="15.01.06 -> 30.01.06" Тогда
   Сообщить("Тест 8 пройден");
Иначе
   Сообщить("Тест 8 не пройден","!!!");
КонецЕсли;

//наложение периодов, где период2 начинается из бесконечности
Если ТекстовыйПериод(ОбщийПериод("15.01.06","15.05.06","","30.01.06"))
="15.01.06 -> 30.01.06" Тогда
   Сообщить("Тест 9 пройден");
Иначе
   Сообщить("Тест 9 не пройден","!!!");
КонецЕсли;

//наложение периодов, где период1 кончается в бесконечности
Если ТекстовыйПериод(ОбщийПериод("14.05.06","","15.01.06","15.05.06"))
="14.05.06 -> 15.05.06" Тогда
   Сообщить("Тест 10 пройден");
Иначе
   Сообщить("Тест 10 не пройден","!!!");
КонецЕсли;

//наложение периодов, где период2 кончается в бесконечности
Если ТекстовыйПериод(ОбщийПериод("15.01.06","15.05.06","14.05.06",""))
="14.05.06 -> 15.05.06" Тогда
   Сообщить("Тест 11 пройден");
Иначе
   Сообщить("Тест 11 не пройден","!!!");
КонецЕсли;

//наложение периодов, где период1 полностью бесконечен
Если ТекстовыйПериод(ОбщийПериод("15.01.06","15.05.06","",""))
="15.01.06 -> 15.05.06" Тогда
   Сообщить("Тест 12 пройден");
Иначе
   Сообщить("Тест 12 не пройден","!!!");
КонецЕсли;

//наложение периодов, где период1 полностью бесконечен, а первый развернут
Если ТекстовыйПериод(ОбщийПериод("15.05.06","15.01.06","",""))
="15.01.06 -> 15.05.06" Тогда
   Сообщить("Тест 13 пройден");
Иначе
   Сообщить("Тест 13 не пройден","!!!");
КонецЕсли;

//наложение двух бесконечных периодов
Если ТекстовыйПериод(ОбщийПериод("","","",""))
="пусто -> пусто" Тогда
   Сообщить("Тест 14 пройден");
Иначе
   Сообщить("Тест 14 не пройден","!!!");
КонецЕсли;

Если ВхождениеПериодов("15.05.06","15.01.06","","")=1 Тогда
   Сообщить("Тест 21 пройден");
Иначе
   Сообщить("Тест 21 не пройден","!!!");
КонецЕсли;

Если ВхождениеПериодов("01.01.06","15.01.06","16.01.06","31.01.06")=0 Тогда
   Сообщить("Тест 22 пройден");
Иначе
   Сообщить("Тест 22 не пройден","!!!");
КонецЕсли;

Если ВхождениеПериодов("","30.01.06","15.01.06","15.05.06")=1 Тогда
   Сообщить("Тест 23 пройден");
Иначе
   Сообщить("Тест 23 не пройден","!!!");
КонецЕсли;

КонецПроцедуры

 

  

2b or not 2b = ff
Наверх
ICQ  
IP записан
 
Kostya
Junior Member
**
Отсутствует



Сообщений: 62
Местоположение: Украина / Луцк
Зарегистрирован: 14. Декабря 2006
Пол: Мужской
Re: Класс Периоды (наложения, вхождения периодов)
Ответ #2 - 23. Января 2007 :: 17:53
Печать  
Полезный класс для зарплаты,  например вывести всех работающих инвалидов на предприятии за период такой то. Соответственно есть три периода. Период отчета, период работы человека, период его инвалидных свидетельств. общие из трех интервалов нужно подавать в соответствующую службу.
  

2b or not 2b = ff
Наверх
ICQ  
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Класс Периоды (наложения, вхождения периодов)
Ответ #3 - 23. Января 2007 :: 19:19
Печать  
Вот вариант реализации общего периода через ИТ:
Код
Выбрать все
Функция ОбщийПериод(Знач НачПериода1, Знач КонПериода1, Знач НачПериода2, Знач КонПериода2) Экспорт;
	НачПериода1 = ?(ПустоеЗначение(НачПериода1) =0, Дата(НачПериода1), Дата(0));
	КонПериода1 = ?(ПустоеЗначение(КонПериода1) =0, Дата(КонПериода1), '31.12.2099');
	НачПериода2 = ?(ПустоеЗначение(НачПериода2) =0, Дата(НачПериода2), Дата(0));
	КонПериода2 = ?(ПустоеЗначение(КонПериода2) =0, Дата(КонПериода2), '31.12.2099');

	_т =СоздатьОбъект("ИндексированнаяТаблица");
	_т.НоваяКолонка("Дата1");
	_т.НоваяКолонка("Дата2");
	_т.НоваяСтрока();
	_т.Дата1 =Мин(НачПериода1, КонПериода1);
	_т.Дата2 =Макс(НачПериода1, КонПериода1);

	_т.НоваяСтрока();
	_т.Дата1 =Мин(НачПериода2, КонПериода2);
	_т.Дата2 =Макс(НачПериода2, КонПериода2);

	_т.ДобавитьИндекс("Дата1", "Дата1");
	_т.ДобавитьИндекс("Дата2", "Дата2");

	_т.ВКонец("Дата1");
	_т.ПредыдущаяСтрока("Дата1");
	_ДатаНачала = _т.Дата1;

	_т.ВНачало("Дата2");
	_т.СледующаяСтрока("Дата2");
	_ДатаКонца =_т.Дата2;

	_сп =СоздатьОбъект("СписокЗначений");
	Если (_ДатаНачала <= _ДатаКонца) Тогда
		_сп.Установить("НачДата",_ДатаНачала);
		_сп.Установить("КонДата",_ДатаКонца);
	КонецЕсли;
	Возврат _сп;
КонецФункции
 


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

Да, и Костя, я что-то не догнал, как это у тебя наложение двух бесконечных периодов дает пустоту?
Т.е. если в каждой руке по чемодану с лавандосом, а в ларьке и мороженого не дадут? Подмигивание
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Kostya
Junior Member
**
Отсутствует



Сообщений: 62
Местоположение: Украина / Луцк
Зарегистрирован: 14. Декабря 2006
Пол: Мужской
Re: Класс Периоды (наложения, вхождения периодов)
Ответ #4 - 23. Января 2007 :: 20:15
Печать  
пусто -> пусто читай та же бесконечность.

Но явно общим периодом для двух пустот не станет
пусто -> 31.12.99, как в случае с ИТ Улыбка)

Так что 14 тест сломался Подмигивание
  

2b or not 2b = ff
Наверх
ICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Класс Периоды (наложения, вхождения периодов)
Ответ #5 - 24. Января 2007 :: 06:38
Печать  
Костя, по тестирование имхо удобнее использовать разработанную спец. систему юнит-тестирования 1С++.
Очень удобно писать тесты, в т.ч. добавлять новые.
Система обнаружения ошибок и куча различных методов для диагностики ошибок очень хорошо сделана.

Мы(разработчики 1С++) эту систему активно юзаем при разработке 1С++.

В репозитариии 1С++ есть спец. каталог Testing, в котором есть все - и система, и скрипты сборки/разборки, и сами тесты 1C++ (почти 700 шт) и дока по написанию тестов Улыбка

Рекомендую.
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Класс Периоды (наложения, вхождения периодов)
Ответ #6 - 24. Января 2007 :: 07:45
Печать  
Kostya писал(а) 23. Января 2007 :: 20:15:
Но явно общим периодом для двух пустот не станет
пусто -> 31.12.99, как в случае с ИТ Улыбка)

Да, тут сказались превратности преобразований 1С.
Пожалуй, надо было за минимум Дата(1) брать, тогда символом бесконечности был бы период "12.31.-471" - "31.12.2099".
Как символ связи между прошлым и будущим Подмигивание
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать