Каталог решений - Преобразование строки в дату

Преобразование строки в дату

Преобразование строки в дату

В наличии

Функция преобразует строку в дату.
Возможные варианты: "27/янв\2015 3-15-22", "1 янв 2005г. ::01", 20150320220315, "2/3/55", "05/3/15", "1 ФеВраЛЯ 05 г. 20:01:0", "1 янв. 2005 г ::",  "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"

Категория:

Описание

Причиной создания этой функции послужил вот такой формат даты «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% универсальность. Только вот, слишком медленная функция получится, наверное. Хотя… надо тестировать. Пока, не критично.  Как идея ВРег(стр)<>НРег(стр) = только буквы — может получится быстрее, чем СтрЗаменить()

Похожие темы:

//sale.itcity.ru/public/200111/
//sale.itcity.ru/public/92455/

has been added to your cart:
Оформление заказа