Определение текущей даты на основании данных онлайн сервисов

24.09.18

Интеграция - WEB-интеграция

Пример получения текущей даты-времени на примере сервиса yandex.ru

Т.к. в свое время я не нашел внятных примеров, решил выложить свой пример для yandex, может кому поможет и сократит время.

Основным родом моей деятельности является синхронизация данных между УС на базе 1С и различными другим базами данных.

Механизм обмена в данном случае не важен, важно другое - период синхронизации и то по долгу службы столкнулся с одной проблемой.

Нередко пользователи переводят дату на компьютере в будущее-прошлое. Причины для этого разные и не буду в них вдаваться. Важно, что при подобной смене метод 1С ТекущаяДата() обращается к параметрам системы и возвращает дату будущую-прошлую, что приводит в моем случае к неверной установке периода синхронизации и, как следствие, к к получению неактуальных данных.

Попытки решить вопрос административно, т.е. запретом изменения даты на компьютере, как правило не приводят к результату, клиент по собственным причинам не желает менять принципы своей работы.

Поэтому было принято решение переопределять текущую дату на основании данных онлайн сервиса.

Были эксперименты с сервисами time.nist.gov, ntp.psn.ru, time.windows.com, timeserver.ru, wwp.greenwichmeantime.com, но yandex.ru показался мне наиболее удачным в плане надежности, т.к. с прочими периодически возникали проблемы соединения.

Для подключения к сервису используется типовое HTTPСоединение и дальнейшее распарсивание строки ответа с приведением к типу Дата.

	//Тело POST-запроса, сюда yandex вернет ответ 
	ТелоPOSTЗапроса = "";
	
	//POST-запрос на сервер-приёмник
	СерверПриемник = "www.yandex.ru"; //имя сервера без протокола (http) и порта
	
	// сформируем пустой запрос, нам от yandex ничего не нужно, а при пустом запросе в ответ он как и пошлет текущее дату-время
	ЗаголовкиHTTP = Новый Соответствие;
	ЗаголовкиHTTP.Вставить("Content-Type", "text/html;charset=UTF-8");

	Таймаут = 120;
	SSL =  Новый ЗащищенноеСоединениеOpenSSL();
	НТТР = Новый HTTPСоединение(СерверПриемник, , , , , Таймаут, SSL);

	Попытка
		//Формируем HTTP запрос
		ЗапросHTTP = Новый HTTPЗапрос("", ЗаголовкиHTTP);
		ЗапросHTTP.УстановитьТелоИзСтроки(ТелоPOSTЗапроса); //Устанавливает строку, из которого будет прочитано тело POST-запроса.
		
		//Ответ от сервера получим в возвращаемом значении типа HTTPОтвет
		ОтветHTTP = НТТР.ОтправитьДляОбработки(ЗапросHTTP);
	Исключение
		ТекстСообщения = НСтр("ru = 'Неудачная попытка соединения с '")  + СерверПриемник + ": " + ОписаниеОшибки();
		Сообщить(ТекстСообщения);
		Возврат;
	КонецПопытки;
	
	ЗаголовкиОтвета = ОтветHTTP.Заголовки;
	Если ЗаголовкиОтвета.Количество() > 0 Тогда
		Для каждого КлючИЗначение Из ЗаголовкиОтвета Цикл
			// в ответе много всякого, но нас интересует только DATE
			Если КлючИЗначение.Ключ = "Date" Тогда
				Сообщить("Дата = " +РаспарситьСтрокуЗначения(КлючИЗначение.Значение, Истина));
				Сообщить("ДатаВремя = " +РаспарситьСтрокуЗначения(КлючИЗначение.Значение, Ложь));
				Прервать;
			КонецЕсли;
		КонецЦикла; //Для каждого КлючИЗначение Из ЗаголовкиОтвета
	КонецЕсли;
	
	ОтветHTTP = NULL;

Самое интересно происходит в процедуре РаспарситьСтрокуЗначения(), которая и занимается разбором ответа от сервиса и приведением его к типу Дата.

Функция ВернутьЧисловойСтрокой(пМесяц)
	
	Если Найти(НРег(пМесяц), "jan") > 0 Тогда
		Возврат "01";
	ИначеЕсли Найти(НРег(пМесяц), "feb") > 0 Тогда
		Возврат "02";
	ИначеЕсли Найти(НРег(пМесяц), "mar") > 0 Тогда
		Возврат "03";
	ИначеЕсли Найти(НРег(пМесяц), "apr") > 0 Тогда
		Возврат "04";
	ИначеЕсли Найти(НРег(пМесяц), "may") > 0 Тогда
		Возврат "05";
	ИначеЕсли Найти(НРег(пМесяц), "jun") > 0 Тогда
		Возврат "06";
	ИначеЕсли Найти(НРег(пМесяц), "jul") > 0 Тогда
		Возврат "07";
	ИначеЕсли Найти(НРег(пМесяц), "aug") > 0 Тогда
		Возврат "08";
	ИначеЕсли Найти(НРег(пМесяц), "sep") > 0 Тогда
		Возврат "09";
	ИначеЕсли Найти(НРег(пМесяц), "oct") > 0 Тогда
		Возврат "10";
	ИначеЕсли Найти(НРег(пМесяц), "nov") > 0 Тогда
		Возврат "11";
	ИначеЕсли Найти(НРег(пМесяц), "dec") > 0 Тогда
		Возврат "12";
	КонецЕсли;
	
КонецФункции

Функция РаспарситьСтрокуЗначения(пЗначение, ТолькоДата = Истина)
	// строка значения заголовка типа DATE  = "Tue, 27 Dec 2016 12:12:49 GMT"
	
	СтрокаДата = "";
	разделитель = ",";
	разделительПробел = " ";
    // местное отклонение по часовому поясу от Гринвича, в примере для простоты объявлено прямо в коде, но рекомендуется выносить в параметры или в реквизиты
	ОтклонениеПоЧасововмуПоясу = 3; 
	
	// отсекаем день недели - остается "27 Dec 2016 12:12:49 GMT"
	позицияРазделитель = Найти(пЗначение, разделитель);
	СтрокаДатаВремя = СокрЛП(Сред(пЗначение, позицияРазделитель+1));
	
	// получаем значение номера дня  - "27"
	позицияРазделительПробел = Найти(СтрокаДатаВремя, разделительПробел);
	СтрокаДень = СокрЛП(Сред(СтрокаДатаВремя, 1, позицияРазделительПробел-1));
	
	// отсекаем номер дня - остается "Dec 2016 12:12:49 GMT"
	СтрокаДатаВремя = СокрЛП(Сред(СтрокаДатаВремя, позицияРазделительПробел+1));
	
	// получаем номер месяца - "Dec", после преобразорвания - "12"
	позицияРазделительПробел = Найти(СтрокаДатаВремя, разделительПробел);
	СтрокаМесяц = СокрЛП(Сред(СтрокаДатаВремя, 1, позицияРазделительПробел-1));
	СтрокаМесяц = ВернутьЧисловойСтрокой(СтрокаМесяц); 
	
	// отсекаем номер месяца - остается "2016 12:12:49 GMT"
	СтрокаДатаВремя = СокрЛП(Сред(СтрокаДатаВремя, позицияРазделительПробел+1));
	
	// получаем номер года - "2016"
	позицияРазделительПробел = Найти(СтрокаДатаВремя, разделительПробел);
	СтрокаГод = СокрЛП(Сред(СтрокаДатаВремя, 1, позицияРазделительПробел-1));
	
	// вычислили дату, если запрашивали только ее, возвращаем
	Если ТолькоДата Тогда
		Возврат Дата(СтрокаГод+СтрокаМесяц+СтрокаДень);
	КонецЕсли;
	
	// вычисляем время
	// отсекам номер года - остается "12:12:49 GMT"
	СтрокаДатаВремя = СокрЛП(Сред(СтрокаДатаВремя, позицияРазделительПробел+1));
	
	// получаем время - "12:12:49", после преобразования - "121249"
	позицияРазделительПробел = Найти(СтрокаДатаВремя, разделительПробел);
	лСтрокаВремя = СокрЛП(Сред(СтрокаДатаВремя, 1, позицияРазделительПробел-1));
	лСтрокаВремя = СтрЗаменить(лСтрокаВремя, ":", "");
	
	// расчитываем время с учетом часового пояса
	лЧасы = Число(Сред(лСтрокаВремя, 1, 2));
	лОстальное = Сред(лСтрокаВремя, 3);
	лЧасы = лЧасы + ОтклонениеПоЧасововмуПоясу;
	СтрокаВремя = Строка(лЧасы) + лОстальное;
	СтрокаВремя = ?(СтрДлина(СтрокаВремя) = 6, СтрокаВремя, "0" + СтрокаВремя);
	
	// возвращаем полный формат даты с временем
	Возврат Дата(СтрокаГод+СтрокаМесяц+СтрокаДень+СтрокаВремя);
	
КонецФункции

В результате имеем надежный, простой и быстрый способ определения точной текущей даты и времени.

конфигурация 8.х

См. также

WEB-интеграция Администрирование веб-серверов Платные (руб)

Веб-портал обеспечивает удобный доступ к конфигурации 1С:ITIL(ИТИЛ), 1С:ITILIUM, Управление IT-отделом 8 через интернет с любого устройства посредством браузера, увеличивая эффективность работы пользователей и снижая нагрузку на сервер. Быстрая инсталляция портала за пару часов, удобный и интуитивно понятный интерфейс и безопасность данных помогут упростить работу с порталом и ускорить выполнение бизнес-процессов компании.

128000 руб.

19.12.2023    3418    5    0    

11

WEB-интеграция Анализ продаж Системный администратор Программист Пользователь Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Управленческий учет Платные (руб)

Модуль "Подсистема интеграции AmoCRM с 1С" позволяет обеспечить единое информационное пространство, в котором пользователи могут эффективно управлять клиентской базой, следить за статусами сделок и поддерживать актуальность данных как в AmoCRM, так и в 1С.

60000 руб.

07.05.2019    35556    70    45    

30

Оптовая торговля Розничная торговля WEB-интеграция 1С:Управление торговлей 10 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Платные (руб)

Онлайн-заказ - это решение для автоматизации процесса оформления заказов на сайте в торговых организациях. Продукт обеспечивает легкое взаимодействие между компанией и клиентами через веб-интерфейс, интегрированный с 1С:Предприятие. Система позволяет снизить операционные расходы, повысить лояльность клиентов и оптимизировать работу отдела продаж.

57600 руб.

26.11.2024    3073    3    3    

5

WEB-интеграция Программист Руководитель проекта Платформа 1С v8.3 1C:Бухгалтерия 1С:Франчайзи, автоматизация бизнеса Платные (руб)

Расширение значительно упрощает написание API на 1С. Веб программисты получают простой и понятный доступ к 1С. Описание API создаётся автоматически и представляется в виде удобном как для человека, так и для программной обработки.

24000 руб.

27.09.2024    5182    5    2    

6

Сайты и интернет-магазины WEB-интеграция Системный администратор Программист Пользователь Платформа 1С v8.3 1C:Бухгалтерия 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    19492    24    22    

20

WEB-интеграция Программист Бизнес-аналитик Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Оптовая торговля, дистрибуция, логистика ИТ-компания Платные (руб)

Модуль "Экспортер" — это расширение для 1С, предназначенное для автоматизации процессов выгрузки данных. Оно позволяет эффективно извлекать, преобразовывать и передавать данные из систем 1С в интеграционную платформу Spot2D. Подсистема упрощает настройку, снижает количество ручных операций и обеспечивает удобный контроль данных.

14400 руб.

20.12.2024    1261    8    2    

10
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Boneman 302 24.09.18 12:27 Сейчас в теме
Идея в принципе хорошая. Возьму на заметку, может где пригодится )
2. AlexPC 24.09.18 13:12 Сейчас в теме
Для клиент-серверного варианта может помочь ТекущаяДатаСеанса()
3. VictorRGB2 14 24.09.18 14:46 Сейчас в теме
(2) проверено, если изменена дата на сервере, вернет опять же измененную дату, а не текущую
собственно проблема и всплыла именно в режиме фоновых заданий, а клиенты менять дату на серверах категорически отказывались
вот и пришлось искать обходной путь
4. AlexPC 24.09.18 15:34 Сейчас в теме
(3)
клиенты менять дату на серверах категорически отказывались


Непонятно. Клиентам было разрешено менять дату на сервере 1с?
5. VictorRGB2 14 24.09.18 16:16 Сейчас в теме
(4) а кто им запретит то? мы не администрируем клиентские сервера, мы лишь поставщики решения по синхронизации данных и не более.
8. MikhailDr 25.09.18 07:41 Сейчас в теме
(5) тут проблема глобальнее, если у клиента есть доступ к серверу 1С, зачем вообще пользователю доступ к серверу
9. AlexPC 25.09.18 19:31 Сейчас в теме
(5)
а кто им запретит то? мы не администрируем клиентские сервера, мы лишь поставщики решения по синхронизации данных и не более.

А синхронизация проходит в рамках локальной сети или через интернет?
10. VictorRGB2 14 26.09.18 08:49 Сейчас в теме
(9) синхронизация через xml, формирование и чтение файлов в локальной сети, отправка и получение файлов через интернет
6. uno-c 267 25.09.18 01:03 Сейчас в теме
&НаКлиенте
Процедура СообщитьТекущееВремя(Команда)
	ХТТП = Новый HTTPСоединение("time.is",,,,,,Новый ЗащищенноеСоединениеOpenSSL);
	Ответ = ХТТП.Получить(Новый HTTPЗапрос("/Unix"));
	СтрокаОтвета = Ответ.ПолучитьТелоКакСтроку();
	Старт = СтрНайти(СтрокаОтвета, "<div id=""twd"">") + 14;
	ЮниксВремя = Число(Сред(СтрокаОтвета, Старт, 10));
	Местное = МестноеВремя(Дата(1970,1,1) + ЮниксВремя);
	Сообщить (Местное);
КонецПроцедуры
Показать
romankoav; A_Max; +2 Ответить
7. uno-c 267 25.09.18 02:13 Сейчас в теме
Можно и по Яндексу, для разнообразия используем объектную модель:
&НаКлиенте
Процедура СообщитьТекущееВремяПоЯндексу(Команда)
	ХТТП = Новый HTTPСоединение("yandex.ru",,,,,,Новый ЗащищенноеСоединениеOpenSSL);
	СтрокаОтвета = ХТТП.Получить(Новый HTTPЗапрос("/time/")).ПолучитьТелоКакСтроку();
	ЧтениеHTML = Новый ЧтениеHTML;
	ЧтениеHTML.УстановитьСтроку(СтрокаОтвета);
	ПостроительDOM = Новый ПостроительDOM;
	ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML);
	СтрокаЖсон = ДокументHTML.Тело.Атрибуты.ПолучитьИменованныйЭлемент("data-bem").Значение;
	ЧтениеЖсон = Новый ЧтениеJSON;
	ЧтениеЖсон.УстановитьСтроку(СтрокаЖсон);
	ЖсонХДТО = ФабрикаXDTO.ПрочитатьJSON(ЧтениеЖсон);
	Сообщить (МестноеВремя(Дата(1970,1,1) + ЖсонХДТО.app.time/1000));
КонецПроцедуры
Показать
verssion; A_Max; mysm; gzharkoj; +4 Ответить
11. markers 278 06.11.18 11:26 Сейчас в теме
Как кто-то сказал "Всё новое - давно забытое старое": https://infostart.ru/public/663042/
Оставьте свое сообщение