Здесь описана функция получения даты из произвольной строки, реализована с целью выявления даты из ячейки счета-фактуры например:
- Счет-фактура № 087-103-5-0014375 от 25.05.20 (1)
- Счет-фактура № 087-103-5-0014375 от 25 января 2020 года
Реализован принцип поиска в строке чего-то похожего на дату. Из всех найденных возможных дат возвращается самая адекватная.
Принцип взят как составления наборов частей дат разделенных пробелами либо разделителями типа ",;/.-\ " начиная с конца, год + месяц + день
Алгоритм не распознает "что угодно" и если сунуть ему хаос из наборов букв и цифр то он ничего не распознает или распознает не верно
Например: 0102523 18мая 2020 3689832 12/12/2020 12\05\2021\ распознается как 12 декабря 2020 года
0102523 18 мая 2020 3689832 12/12/2020 12\05\2021\ распознается как 18 мая 2020 года
Т.к. во входящих документах обычно все же есть какая то логика алгоритм обрабатывает 100% входящих дат, за время работы ошибок не выявлено.
Здесь приведен код распознавания:
Функция Вернутьдату(Строка)
Имена = новый Структура;
Имена.Вставить("ЯНВАРЬ", 1);
Имена.Вставить("ФЕВРАЛЬ",2);
Имена.Вставить("МАРТ", 3);
Имена.Вставить("АПРЕЛЬ", 4);
Имена.Вставить("МАЙ", 5);
Имена.Вставить("МАЯ", 5);
Имена.Вставить("ИЮНЬ", 6);
Имена.Вставить("ИЮЛЬ", 7);
Имена.Вставить("АВГУСТ", 8);
Имена.Вставить("СЕНТЯБРЬ", 9);
Имена.Вставить("ОКТЯБРЬ", 10);
Имена.Вставить("НОЯБРЬ", 11);
Имена.Вставить("ДЕКАБРЬ", 12);
Имена.Вставить("ЯНВАРЯ", 1);
Имена.Вставить("ФЕВРАЛЯ",2);
Имена.Вставить("МАРТА", 3);
Имена.Вставить("АПРЕЛЯ", 4);
Имена.Вставить("ИЮНЯ", 6);
Имена.Вставить("ИЮЛЯ", 7);
Имена.Вставить("АВГУСТА", 8);
Имена.Вставить("СЕНТЯБРЯ", 9);
Имена.Вставить("ОКТЯБРЯ", 10);
Имена.Вставить("НОЯБРЯ", 11);
Имена.Вставить("ДЕКАБРЯ", 12);
МасСтрок = _РазбитьСтроку(Строка,",;/.-\ ");
МасЦифр = Новый Массив;
МасВозврата = Новый ТаблицаЗначений;
КД = новый КвалификаторыДаты(Частидаты.Дата);
МКв = новый Массив();
Мкв.Добавить(Тип("Дата"));
МасВозврата.Колонки.Добавить("датаОп", Новый ОписаниеТипов(МКв,,КД));
Для каждого стр из МасСтрок Цикл
НЗ = "";
СтрПроверки = УбратьСпецСимволыРус(ВРЕГ(СокрЛП(стр)));
ПС = Лев(СтрПроверки,1);
Если НЕ ТолькоЦифры(СтрПроверки) и НЕ ТолькоЦифры(ПС) Тогда
Если Имена.Свойство(СтрПроверки, НЗ) Тогда
МасСтрок[МасСтрок.найти(СтрПроверки)] = НЗ;
КонецЕсли;
Иначе
НЗ = стр;
КонецЕсли;
НовЦифра = "";
Для аа=1 по СтрДлина(НЗ) Цикл
Сим = Сред(НЗ,аа,1);
Если ТолькоЦифры(Сим) Тогда
НовЦифра = НовЦифра + Сим;
КонецЕсли;
КонецЦикла;
Если ЗначениеЗаполнено(НовЦифра)Тогда
МасЦифр.Вставить(0,НовЦифра);
КонецЕсли;
КонецЦикла;
Если МасЦифр.Количество()<3 Тогда
Возврат Дата('00010101');
КонецЕсли;
Активно = истина;
Пока Активно Цикл
Если МасЦифр.Количество()<3 Тогда
прервать;
КонецЕсли;
Если СтрДлина(МасЦифр[0])<4 Тогда
Год = "000" + МасЦифр[0];
Год = Прав(Год,3);
Год = "2" + Год;
ИначеЕсли СтрДлина(МасЦифр[0])>4 Тогда
МасЦифр.Удалить(0);
Продолжить;
Иначе
Год = МасЦифр[0];
КонецЕсли;
Если СтрДлина(МасЦифр[1])<2 Тогда
Месяц = "0" + МасЦифр[1];
ИначеЕсли СтрДлина(МасЦифр[1])>2 или Число(МасЦифр[1])>12 Тогда
МасЦифр.Удалить(0);
Продолжить;
Иначе
Месяц = МасЦифр[1];
КонецЕсли;
Если СтрДлина(МасЦифр[2])<2 Тогда
День = "0" + МасЦифр[2];
ИначеЕсли СтрДлина(МасЦифр[2])>2 или Число(МасЦифр[2])>31 Тогда
МасЦифр.Удалить(0);
Продолжить;
Иначе
День = МасЦифр[2];
КонецЕсли;
СтрокаДля = Год + Месяц + День;
Попытка
датаВозвр = дата(СтрокаДля);
Доб = МасВозврата.Добавить();
доб.ДатаОп = датаВозвр;
МасВозврата.Добавить(датаВозвр);
МасЦифр.Удалить(0);
Исключение
МасЦифр.Удалить(0);
КонецПопытки;
КонецЦикла;
Если МасВозврата.Количество() > 1 Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| даты.ДатаОп
|ПОМЕСТИТЬ ДОпр
|ИЗ
| &даты КАК даты
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| МИНИМУМ(ВЫБОР
| КОГДА РАЗНОСТЬДАТ(ДОпр.ДатаОп, &ТД, ДЕНЬ) < 0
| ТОГДА -РАЗНОСТЬДАТ(ДОпр.ДатаОп, &ТД, ДЕНЬ)
| ИНАЧЕ РАЗНОСТЬДАТ(ДОпр.ДатаОп, &ТД, ДЕНЬ)
| КОНЕЦ) КАК Поле1,
| ДОпр.ДатаОп
|ПОМЕСТИТЬ Вт2
|ИЗ
| ДОпр КАК ДОпр
|
|СГРУППИРОВАТЬ ПО
| ДОпр.ДатаОп
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| МИНИМУМ(Вт2.Поле1) КАК Поле1
|ПОМЕСТИТЬ ВТМИН
|ИЗ
| Вт2 КАК Вт2
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Вт2.ДатаОп,
| ВТМИН.Поле1,
| Вт2.Поле1 КАК Поле11
|ИЗ
| Вт2 КАК Вт2
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТМИН КАК ВТМИН
| ПО Вт2.Поле1 = ВТМИН.Поле1";
Запрос.УстановитьПараметр("Даты",МасВозврата);
Запрос.УстановитьПараметр("ТД", Текущаядата());
Рез = Запрос.Выполнить().Выгрузить();
Возврат Рез[0].ДатаОп;
ИначеЕсли МасВозврата.Количество() = 1 Тогда
Возврат МасВозврата[0].датаОп;
Иначе
Возврат Дата('00010101');
КонецЕсли;
КонецФункции
Функции РазбитьСтроку, ТолькоЦифры и УбратьСпецСимволы можно написать самому или взять в приложенной обработке
Обработка выполнена на обычной форме под платформой 1С:Предприятие 8.3 (8.3.16.1296)
Процедуры и функции используются в модуле управляемой формы &НаСервере