Как получить значение поля TIME из базы Firebird в 1С 7.7 через ADO

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При работе с внешними базами данных, такими как Firebird, из среды 1С:Предприятие 7.7 через интерфейс ADO (ActiveX Data Objects), разработчики часто сталкиваются с неожиданным поведением при чтении специфических типов данных. Одной из наиболее коварных проблем является работа с типом TIME. Вместо ожидаемого значения времени (например, "14:30:00"), система может возвращать текущую дату или пустые значения. В этой статье мы подробно разберем, почему это происходит и как правильно организовать чтение данных, чтобы избежать искажений.

Анализируем причину возникновения ошибки

Для начала проанализируем ситуацию: почему в IBExpert или других SQL-менеджерах запрос SELECT t FROM table возвращает корректное время, а в 1С мы видим «ерунду» или текущую системную дату? Причина кроется в многослойности передачи данных. Когда запрос выполняется через ADO, данные проходят через цепочку: Firebird Engine -> ODBC/OLE DB Driver -> ADO COM-объект -> 1С 7.7.

Рассмотрим технические детали маппинга типов. В Firebird (начиная с Dialect 3) тип TIME хранит только время. Однако в стандарте COM, на котором построена работа 1С 7.7 с объектами ADODB.Recordset, наиболее близким типом является VT_DATE. Тип DATE в COM/Automation — это число с плавающей точкой, где целая часть отвечает за дату, а дробная — за время.

Поскольку в поле TIME информация о дате отсутствует, многие драйверы (особенно старые версии Firebird ODBC Driver) пытаются «достроить» значение до полноценного TIMESTAMP. В результате они подставляют либо базовую дату (30.12.1899), либо — что чаще всего и путает разработчиков — текущую системную дату. Платформа 1С 7.7, в свою очередь, имеет тип Дата, который хранит только число, месяц и год без времени. При получении объекта VT_DATE от ADO, 1С отбрасывает дробную часть, оставляя только дату. Именно поэтому в отладчике мы видим текущее число вместо времени.

Метод 1: Использование «хитрого» преобразования в строку (CAST)

Первое решение, которое приходит на ум — использовать CAST(поле AS CHAR). Однако обычный CAST в SQL-запросе не всегда спасает. Если драйвер вернет строку, которая по формату напоминает дату, ADO или сама 1С может попытаться выполнить неявное преобразование обратно в тип Дата.

Чтобы гарантированно получить строковое представление времени, мы применим проверенный прием: добавим к результату пустой символ или любой нецифровой префикс. Это заставит систему воспринимать данные строго как текст.

Рассмотрим пример правильного SQL-запроса для 1С 7.7:


// В коде 1С формируем текст запроса
ТекстЗапроса = "SELECT ' ' || CAST(ИмяПоляВремени AS CHAR(8)) as TimeStr FROM МояТаблица";
// Символ пробела в начале предотвращает автоматическую конвертацию в тип Дата

Разберем, что происходит в этом коде. Мы используем оператор конкатенации ||, чтобы добавить пробел к строковому представлению времени. Теперь при обращении к Recordset.Fields("TimeStr").Value 1С получит строку вида " 12:30:00", которую легко обработать стандартными функциями СокрЛП() или Лев() / Прав().

Метод 2: Извлечение компонентов времени через EXTRACT

Если работа со строками кажется вам недостаточно надежной или формат времени в системных настройках сервера может меняться, воспользуемся более «математическим» подходом. Мы можем извлечь часы, минуты и секунды по отдельности в виде целых чисел. Это исключает любые ошибки интерпретации типов драйвером.

Проанализируем пример реализации этого метода:


ТекстЗапроса = "
|SELECT 
|  EXTRACT(HOUR FROM ИмяПоляВремени) as h, 
|  EXTRACT(MINUTE FROM ИмяПоляВремени) as m, 
|  EXTRACT(SECOND FROM ИмяПоляВремени) as s 
|FROM МояТаблица";

// В 1С получаем результат
Часы = Рекордсет.Fields("h").Value;
Минуты = Рекордсет.Fields("m").Value;
Секунды = Рекордсет.Fields("s").Value;

// Собираем время в строку для 1С
СтрокаВремени = Формат(Часы, "Ч(0)2") + ":" + Формат(Минуты, "Ч(0)2") + ":" + Формат(Секунды, "Ч(0)2");

Этот метод является наиболее устойчивым, так как числа передаются через COM без искажений. Мы получаем полный контроль над формированием значения времени внутри кода 1С.

Метод 3: Настройка провайдера данных (OLE DB)

Если вы используете специфические провайдеры, например LCPI.IBProvider, проблему можно решить на уровне настроек подключения. Проанализируем возможности драйвера: в строке подключения можно указать параметры маппинга типов, которые заставят провайдер возвращать тип TIME как строку автоматически.

Например, использование нативного провайдера вместо стандартного MSDASQL (который является оберткой над ODBC) часто решает проблему «магического» превращения времени в текущую дату. В настройках DSN (Data Source Name) также стоит обратить внимание на параметр Timestamp Format, хотя для чистого типа TIME он имеет меньшее значение, чем формат приведения к строке.

Подводим итоги и рекомендации

Выясним причину еще раз: корень зла — в попытке ADO представить время как VT_DATE и неспособности 1С 7.7 хранить время в типе Дата.

Для стабильной работы мы рекомендуем придерживаться следующих правил:

  1. Всегда проверяйте тип возвращаемого значения в 1С с помощью функции ТипЗначенияСтр(). Если вы видите "Дата", значит, произошло неявное преобразование.
  2. Для получения времени из Firebird используйте либо CAST с добавлением пробела в начале строки, либо функцию EXTRACT для получения чисел.
  3. Если база данных работает в третьем диалекте (Dialect 3), помните, что поля TIME и TIMESTAMP ведут себя по-разному. Поле TIMESTAMP через ADO в 1С 7.7 почти всегда превращается в дату без времени, поэтому к нему применимы те же методы «строковой фиксации».

Рассмотренные подходы позволяют обойти ограничения устаревшей платформы 1С 7.7 и корректно интегрировать её с современными версиями Firebird, обеспечивая точность данных в управленческом и техническом учете.

← На главную