Причиной создания этой функции послужил вот такой формат даты «1 Января 2015 г. 13:25». И чтобы сто раз не возвращаться к теме, сделал что-то универсальное, дабы не тратить время в будущем.
В функции много комментариев.
Для более быстрой адаптации к др.языкам (локализация) создан массив п_мФорматы()
// для тестов:
//Сообщить(СтрВДату("20:01:0"));
//Сообщить(СтрВДату("27/08\2015 3-15-22"));
//Сообщить(СтрВДату(20150320220315));
//Сообщить(СтрВДату("2/3/55"));
//Сообщить(СтрВДату("05/3/15"));
//Сообщить(СтрВДату("1 ФеВраЛя 05 г. 20:01:0"));
//Сообщить(СтрВДату("1 янв. 2005 г ::"));
//Сообщить(СтрВДату("1 янв 2005г. ::01"));
//Сообщить(СтрВДату("1 янв 2005г ::01"));
//Сообщить(СтрВДату("1 ФеВраЛь 05 г. 0:02:"));
//Сообщить(СтрВДату("1 янВа 2005 г. 20:01"));
//Сообщить(СтрВДату("02/04/2015"));
//Сообщить(СтрВДату("20150320220315"));
//Сообщить(СтрВДату("27.08.2015 3:15:22"));
//Сообщить(СтрВДату("27.08-2015 5:24"));
// Преобразует строку в дату
// Параметры
// сДата – строка
// Возвращаемое значение:
// дата - тип.дата
//
Функция СтрВДату(Знач сДата) Экспорт
Перем п_мТЕМП; // массив временных переменных
//-----для локализации ------------------------------
Перем п_мФорматы;
п_мФорматы = Новый Массив(4);
п_мФорматы[0] = "г"; // знак года
п_мФорматы[1] = "ЧЦ=2; ЧН=; ЧВН=";
п_мФорматы[2] = "ЧГ=0";
п_мФорматы[3] = "ДФ=МММ";
//---------------------------------------------------
Если ПустаяСтрока(сДата) Тогда
п_мТЕМП[6] =Дата("00010101000000");
Возврат п_мТЕМП[6];
КонецЕсли;
сДата = Формат(сДата, п_мФорматы[2]); //на случай если в формате 1с числом: 20150320220315. (+локализация)
//Если использовать конструкцию "Если Найти(сДата,..." , то перебор букв строки будет происходить 2а раза: Найти и СтрЗаменить //Использование Найти в данном случае бессмысленно
// можно добавить любой разделитель - @, #, %, и тд, неважно. Главное, заменить их на "."
сДата = СтрЗаменить(сДата, "«", ""); //«1 Фев 05 г.»
сДата = СтрЗаменить(сДата, "»", ""); //«1 Фев 05 г.»
сДата = СтрЗаменить(сДата, п_мФорматы[0] + ".", ""); //1 Фев 05 г. 17:20:00 //просто "г" нельзя из-за "авГуст", например. Но в далее,после парсинга месяца, любое "г" в строке, удаляется
сДата = СтрЗаменить(сДата, "/", "."); // 1/2/5
сДата = СтрЗаменить(сДата, "\", "."); // 1\02\05
сДата = СтрЗаменить(сДата, "-", "."); // 1-02-05
сДата = СтрЗаменить(сДата, Символы.Таб, "."); // 01.02.2005 17:20:00
сДата = СтрЗаменить(сДата, " ", "."); // 1/02 2005 17:20:00
сДата = СтрЗаменить(сДата, "..", "."); //Возможны, появление двойных точек из за "янв." в "янв" или из-за " г. ".
сДата = НРег(СокрЛП(сДата)); // строку в нижний регистр, чтоб проще было с Янв Январь янв и тд
п_мТЕМП = Новый массив(7);//массив для временных переменных
п_мТЕМП[0] = Найти(сДата,".");
Если п_мТЕМП[0] = 0 Тогда
//если точек нет
Если Найти(сДата,":") Тогда
//только время (или ошибка)
сДата = "01.01.0001." + сДата;
п_мТЕМП[0] = Найти(сДата,".");
иначе
//похоже на формат 1с. Можно добавить "попытку"...
п_мТЕМП[6] = дата(сДата);
Возврат п_мТЕМП[6];
КонецЕсли;
//иначеЕсли п_мТЕМП[0] = 1 Тогда
// //например, месяц и год
КонецЕсли;
// ----- ДНИ -------------------------------------
п_мТЕМП[0] = Лев(сДата, п_мТЕМП[0] - 1);//дни
п_мТЕМП[4] = Прав(сДата, СтрДлина(сДата) - СтрДлина(п_мТЕМП[0])-1);// месяц и все что справа
п_мТЕМП[0] = Формат(Число(п_мТЕМП[0]),п_мФорматы[1]);//дни в формат двух чисел
// ----- Месяц -----------------------------------
п_мТЕМП[1] = Лев(п_мТЕМП[4], найти(п_мТЕМП[4],".") - 1);// месяц
п_мТЕМП[4] = Прав(п_мТЕМП[4], СтрДлина(п_мТЕМП[4]) - СтрДлина(п_мТЕМП[1])-1);// год и все что справа
//Возможны варианты месяца "янв" "янв." "январь" "января"
Если СтрДлина(п_мТЕМП[1]) > 2 Тогда // месяц в виде янв или январь
п_мТЕМП[2] = 0;
Пока п_мТЕМП[2] < 12 Цикл
п_мТЕМП[2] = п_мТЕМП[2]+1;
// берем из "янв." только "янв"
п_мТЕМП[3] = СтрЗаменить(Формат(Дата("2001" + Формат(п_мТЕМП[2],п_мФорматы[1]) + "01"), п_мФорматы[3]),".","");// + локализация
п_мТЕМП[3] = найти(п_мТЕМП[1], п_мТЕМП[3]);
Если п_мТЕМП[3] > 0 тогда
п_мТЕМП[1] = Формат(п_мТЕМП[2],п_мФорматы[1]);
прервать;
КонецЕсли;
КонецЦикла;
Иначе
п_мТЕМП[1] = Формат(Число(п_мТЕМП[1]),п_мФорматы[1]);
КонецЕсли;
// ----- ГОД -----------------------------------
//Если в строке было "г" без точки("г.")
п_мТЕМП[4] = СтрЗаменить(п_мТЕМП[4], п_мФорматы[0], "");
//ищем год. Дата может быть без времени, т.е. год последний в строке
п_мТЕМП[2] = Найти(п_мТЕМП[4],".");
Если п_мТЕМП[2]>0 Тогда
п_мТЕМП[2] = Лев(п_мТЕМП[4], п_мТЕМП[2] - 1);// год
п_мТЕМП[4] = Прав(п_мТЕМП[4], СтрДлина(п_мТЕМП[4]) - СтрДлина(п_мТЕМП[2])-1);//время и все что справа
Иначе
п_мТЕМП[2] = п_мТЕМП[4];
п_мТЕМП[4] = "";
КонецЕсли;
//проверяем год
п_мТЕМП[3] = СтрДлина(п_мТЕМП[2]);
//если год из двух цыфр
Если п_мТЕМП[3] = 2 или п_мТЕМП[3] = 1 Тогда
п_мТЕМП[3] = Число(п_мТЕМП[2]);// год как число
//что означает 15 в "20.03.15"? это 2015г или 1915г? (Настраиваем под себя или выдаём ошибку)
// в моем варианте если < 50 то это 2000г. иначе 1900г.
Если п_мТЕМП[3] < 50 Тогда
п_мТЕМП[2] = "20" + Формат(п_мТЕМП[3],п_мФорматы[1]);
Иначе
п_мТЕМП[2] = "19" + Формат(п_мТЕМП[3],п_мФорматы[1]);
КонецЕсли;
КонецЕсли;
// ======================= Форматируем время ==============================
п_мТЕМП[6] = СтрЗаменить(п_мТЕМП[4],":", ".");// если дата была, например: 17-30-10, то сейчас 17.30.10
//"попытка" на преобразование даты, по времени, занимает столько же, а по ресурсам больше, чем сам парсинг времени.
//поэтому, убиваем двух зайцев перебором часы/мин/сек сразу
Если СтрДлина(п_мТЕМП[6]) > 0 Тогда
п_мТЕМП[5] = найти(п_мТЕМП[6],".");
Если п_мТЕМП[5] > 0 Тогда
// ========= часы =================
п_мТЕМП[3] = Лев(п_мТЕМП[6], найти(п_мТЕМП[6],".") - 1);//часы
п_мТЕМП[6] = Прав(п_мТЕМП[6], СтрДлина(п_мТЕМП[6]) - СтрДлина(п_мТЕМП[3])-1);// минуты и все что справа
Если п_мТЕМП[3] = "" тогда
п_мТЕМП[3] = "00";
Иначе
//при переводе в дату лидирующий 0 у часов удаляется. Т.е. след. строка бесполезна
//п_мТЕМП[3] = Формат(Число(п_мТЕМП[3]),п_мФорматы[1]);//часы в формат двух чисел
КонецЕсли;
п_мТЕМП[5] = найти(п_мТЕМП[6],".");
Если п_мТЕМП[5] > 0 Тогда
// ========= минуты =================
п_мТЕМП[4] = Лев(п_мТЕМП[6], найти(п_мТЕМП[6],".") - 1);
п_мТЕМП[6] = Прав(п_мТЕМП[6], СтрДлина(п_мТЕМП[6]) - СтрДлина(п_мТЕМП[4])-1);// секунды и все что справа
Если п_мТЕМП[4] = "" тогда
п_мТЕМП[4] = "00";
Иначе
п_мТЕМП[4] = Формат(Число(п_мТЕМП[4]),п_мФорматы[1]);//минуты в формат двух чисел
КонецЕсли;
// ========= секунды =================
Если СтрДлина(п_мТЕМП[6]) = 0 Тогда
п_мТЕМП[5] = "00";
Иначе
п_мТЕМП[5] = Формат(Число(п_мТЕМП[6]),п_мФорматы[1]);//секунды в формат двух чисел
КонецЕсли;
Иначе
п_мТЕМП[4] = Формат(Число(п_мТЕМП[6]),п_мФорматы[1]);
п_мТЕМП[5] = "00";
КонецЕсли;
Иначе
п_мТЕМП[3] = Формат(Число(п_мТЕМП[6]),п_мФорматы[1]);
п_мТЕМП[4] = "00";
п_мТЕМП[5] = "00";
КонецЕсли;
Иначе
п_мТЕМП[3] = "00";
п_мТЕМП[4] = "00";
п_мТЕМП[5] = "00";
КонецЕсли;
п_мТЕМП[6] = п_мТЕМП[0] + "." + п_мТЕМП[1] + "." + п_мТЕМП[2] + " " + п_мТЕМП[3] + ":" + п_мТЕМП[4] + ":" + п_мТЕМП[5];
п_мТЕМП[6] = дата(п_мТЕМП[6]);
Возврат п_мТЕМП[6];
КонецФункции
Кто-то заметит, что можно сделать "проще", добавив разделители даты и времени в параметры функции. Но, может попасться "свалка" с различными форматами и тут уже придется долго перебирать все варианты. Поэтому я остановился на множественном "Поиск и Замене"(СтрЗаменить()) вероятных разделителей.
Также, задумывалось, что будут возвращаться параметрами функции (Год, Месяц, День....), но в последствии я от этого отказался. В коде присутствуют остатки от этой затеи, которые не влияют на скорость,а лишь несколько строк(присвоение значений промежуточным переменным) можно сократить.
Конечно, замечания и критика приветствуются. Спасибо.
Пс:
Можно добавить в поиск/замену слово "год".
А в идеале, нужно заменить всё, кроме букв и цифр, на "."(точку) - 100% универсальность. Только вот, слишком медленная функция получится, наверное. Хотя... надо тестировать. Пока, не критично. Как идея ВРег(стр)<>НРег(стр) = только буквы - может получится быстрее, чем СтрЗаменить()
Похожие темы:
//infostart.ru/public/200111/
//infostart.ru/public/92455/