Неверная дата и время

Страницы: 1
RSS
Неверная дата и время, Стандартные функции Lua возвращают неверное время сервера
 
Тестирую вот такой код:

dt = {}
dt.day,dt.month,dt.year,dt.hour,dt.min,dt.sec = string.match(getInfoParam('TRADEDATE')..' '..getInfoParam('SERVERTIME'),"(%d*).(%d*).(%d*) (%d*):(%d*):(%d*)")
message (tostring(dt.day).."-"..tostring(dt.hour)..":"..tostring(dt.min)..":"..tostring(dt.sec))

Сейчас, 12 февраля в 02 часа ночи, однако результат исполнения кода дает время - 9 февраля, 12 часов дня. При этом в строке сообщений Quik время выводится верное (оно берется из компа?)
Выглядит строка сообщений приблизительно так:
2:17:29  09-12:17:29

Почему время сервера сильно отстает от реального? У меня из-за этого проблемы с исполнением кода...
 
Иван Ру,

Время в сообщениях, это время Вашего компьютера.
SERVERTIME это время сервера.
И эти времена совершенно не обязаны совпадать. Никто кроме Вас не может гарантировать что время на Вашем компьютере синхронизировано с компьютером брокера.

TRADEDATE показывает дату торговой сессии. Это не тоже самое что астрономическая дата.
Дата торговой сессии это дата когда проводились торги.
Последний раз они проводились в пятницу, 9-го числа.
 
Цитата
Sergey Gorokhov написал:
Иван Ру  ,

Время в сообщениях, это время Вашего компьютера.
SERVERTIME это время сервера.
И эти времена совершенно не обязаны совпадать. Никто кроме Вас не может гарантировать что время на Вашем компьютере синхронизировано с компьютером брокера.

TRADEDATE показывает дату торговой сессии. Это не тоже самое что астрономическая дата.
Дата торговой сессии это дата когда проводились торги.
Последний раз они проводились в пятницу, 9-го числа.
1. Все нормально синхронизировано. На компьютере время точное - проблема не в этом, а как Вы верно заметили, в том что сервер выдает время последних торгов, которое не всегда актуально.
2. Это значит, что считывание актуального времени (в виде таблицы) с помощью квик и луа -- простейшая, казалось бы, задача, -- становится очень нетривиальным действом.
Просто так считать с помощью date | time его нельзя. Необходимо рассчитывать разницу между поясным временем и временем Гринвича, конвертировать время в формат POSIX, добавлять нужную величину, а затем конвертировать время POSIX в таблицу.
Т.е. получение ключевого простейшего показателя требует выполнения четырех ресурсоемких функций!! Или может я что-то недопонимаю и есть более простой путь?
 
Иван Ру,

А что Вы хотите получить?
Если Дату/Время Вашего компьютера, то есть штатная Lua функция os.date()
 
если надо в виде таблицы, тогда так:
local Ttime = os.date("!*t",os.time())
 
Цитата
Sergey Gorokhov написал:
Иван Ру  ,

А что Вы хотите получить?
Если Дату/Время Вашего компьютера, то есть штатная Lua функция os.date()
Нееет... эта функция возвращает время по Гринвичу, которое не совпадает с локальным временем компьютера и с временем сервера.
Я уже реализовал получение точного локального времени, но выглядит эта конструкция очень громоздко - потребовалось 8 операций, включая 5 вызовов функции даты и времени!

-- ТЕКУЩЕЕ ЛОКАЛЬНОЕ (ПОЯСНОЕ) ВРЕМЯ (POSIX + ТАБЛИЦА)
function fTimeLocal(offset) -- offset - смещение поясного времени в секундах (целое положительное или отрицательное цифровое значение)
if offset == nil then offset = os.offset() ; end -- если не получили временной сдвиг, рассчитываем его по стандартной функции
local posix = os.time()-- считываем текущее время ПК в формате POSIX
posix = posix + offset-- добавляем поясной сдвиг
local datetime = os.date("!*t", posix)-- переводим в формат таблицы
return posix, datetime-- возвращаем полученные значения
end

-- СМЕЩЕНИЕ ВРЕМЕНИ ОТНОСИТЕЛЬНО ГРИНВИЧА ЛОКАЛЬНОЕ / ПОЯСНОЕ ВРЕМЯ К ГРИНВИЧУ - (СЕКУНДЫ)
function os.offset()
  local currenttime = os.time()
  local datetime = os.date("!*t",currenttime)
  datetime.isdst = true -- Флаг дневного времени суток
  return currenttime - os.time(datetime)
end
 
Цитата
Иван Ру написал:
Нееет... эта функция возвращает время по Гринвичу, которое не совпадает с локальным временем компьютера и с временем сервера.

Это не так.
Код
message ('time='..os.date())
 
К слову, в терминале версии 7.16 добавлена функция os.sysdate, позволяющая получить локальное время с точностью до микросекунд.
 
Цитата
Sergey Gorokhov написал:
Цитата
Иван Ру   написал:
Нееет... эта функция возвращает время по Гринвичу, которое не совпадает с локальным временем компьютера и с временем сервера.
Это не так.
Код
   message  ( 'time='  ..  os.date ())  
Попробуйте получить время posix с помощью os.time, а затем конвертировать его во время в табличном формате. Получится рассинхронизация
Посмотрите на пример кода и полученный результат

КОД:
local posix = os.time()
message ('os.time()'.."-"..tostring(posix))
local ttime = os.date()
message ('os.date()'.."-"..tostring(ttime))
local posixToDate = os.date("!*t", posix)
local posixToDateStr = posixToDate.hour..":"..posixToDate.min
message ('Convert os.date() result to posix'.."-"..tostring(posixToDateStr))

РЕЗУЛЬТАТ ИСПОЛНЕНИЯ:


Мои скрипты первоначально считывали время и дату сервера и уже ее конвертировали в формат posix, но я столкнулся с проблемой -- периодически выскакивала ошибка типа "в таблице отсутствует поле day/hour и т.п.). Каких либо закономерностей не обнаружил, я так понял, что это связано с потерей пакетов при загрузке интернет-канала или какими-то другими проблемами связанными с соединением локальной машины и сервера -- поэтому от этого способа пришлось отказаться.  
 
Иван Ру,
Уберите знак "!"
Код
local posixToDate = os.date("*t", posix) 
 
Цитата
Sergey Gorokhov написал:
Иван Ру  ,
Уберите знак "!"
Код
   local  posixToDate  =   os.date ( "*t" , posix)   
Да, так все совпадает. Спасибо.  
 
Цитата
Sergey Gorokhov написал:
Иван Ру  ,
Уберите знак "!"
Код
   local  posixToDate  =   os.date ( "*t" , posix)   
надо только добавить, что так можно делать только если часовой пояс вашего компьютера совпадает с часовым поясом биржи или Квик настроен на трансляцию времени в локальном поясном времени. В остальных случаях будет по прежнему несостыковка
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Цитата
s_mike@rambler.ru написал:
Цитата
Sergey Gorokhov   написал:
Иван Ру  ,
Уберите знак "!"
Код
      local   posixToDate   =    os.date (  "*t"  , posix)     
надо только добавить, что так можно делать только если часовой пояс вашего компьютера совпадает с часовым поясом биржи или Квик настроен на трансляцию времени в локальном поясном времени. В остальных случаях будет по прежнему несостыковка
Совпадают.
В принципе для обхода проблемы я применял вот такие функции, пользуйтесь кому нужно и критикуйте кто может


-- ТЕКУЩЕЕ ВРЕМЯ ПО ГРИНВИЧУ (ТАБЛИЦА)
function fTimeGrinvichTable()
dtServ = {};
dtServ = os.date("!*t",os.time())
for key,value in pairs(dtServ) do dtServ[key] = tonumber(value) end
return dtServ
end

-- ТЕКУЩЕЕ ЛОКАЛЬНОЕ (ПОЯСНОЕ) ВРЕМЯ (POSIX)
function fTimeLocalPosix(offset) -- offset - смещение поясного времени в секундах (целое положительное или отрицательное цифровое значение)
if offset == nil then offset = os.offset() ; end -- если не удалось считать временной сдвиг, рассчитываем его по стандартной функции
local posix = os.time()-- считываем текущее время ПК в формате POSIX
posix = posix + offset-- добавляем поясной сдвиг
return posix -- возвращаем полученные значения
end

-- ТЕКУЩЕЕ ЛОКАЛЬНОЕ (ПОЯСНОЕ) ВРЕМЯ (POSIX + ТАБЛИЦА)
function fTimeLocal(offset) -- offset - смещение поясного времени в секундах (целое положительное или отрицательное цифровое значение)
if offset == nil then offset = os.offset() ; end -- если не удалось считать временной сдвиг, рассчитываем его по стандартной функции
local posix = os.time()-- считываем текущее время ПК в формате POSIX
posix = posix + offset-- добавляем поясной сдвиг
local datetime = os.date("!*t", posix)-- переводим в формат таблицы
return posix, datetime-- возвращаем полученные значения
end

-- СМЕЩЕНИЕ ВРЕМЕНИ ОТНОСИТЕЛЬНО ГРИНВИЧА ЛОКАЛЬНОЕ / ПОЯСНОЕ ВРЕМЯ К ГРИНВИЧУ - (СЕКУНДЫ)
function os.offset()
  local currenttime = os.time()
  local datetime = os.date("!*t",currenttime)
  datetime.isdst = true -- Флаг дневного времени суток
  return currenttime - os.time(datetime)
end

-- ДОПОЛНЕНИЕ ТАБЛИЦЫ ВРЕМЕНИ (Добавляет к поляем времени поля текущей даты, а также поле 'posix' с данными в соотв. формате)
function curDayToPosix (timeTab, dateTab, offset) -- timeTab -- таблица со временем, но без полей дат, dateTab - таблица с полями дат
if offset == nil then offset = os.offset() ; end -- если не удалось считать временной сдвиг, рассчитываем его по стандартной функции
-- устанавливаем в поля даты значения текущего дня
timeTab.year = dateTab.year
timeTab.month = dateTab.month
timeTab.day = dateTab.day
timeTab.posix = os.time (timeTab) + offset
end  
 
Смещение локального часового пояса относительно Гринвича в виде таблицы:
os.date("*t", 0)
(по часам компьютера с учетом региональных настроек операционки, корректно работает для всех случаев, в т.ч. особые часовые пояса, в которых нет перевода на летнее/зимнее время и в тех, где смещение не в целых часах; может Вы из Тегерана торгуете :shock: )
 
Подскажите как получить текущие дату/время сервера в формате "20201023_2345"?
 
Во времени сервера нет миллисекунд.
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Цитата
MrLex написал:
Подскажите как получить текущие дату/время сервера в формате "20201023_2345"?
Если секунды не нужны - закомментируйте их

Код
local function serverTime ()                               -- функция расчета времени сервера

   local ser_time = getInfoParam ("SERVERTIME")

   if ser_time and #ser_time == 8 then
       return string.sub (ser_time, 1, 2) .. string.sub (ser_time, 4, 5) .. string.sub (ser_time, 7, 8) 
     else
       return false 
   end

end

local function serverDate ()                               -- функция расчета даты сервера

   local ser_date = getInfoParam ("TRADEDATE")
   return string.sub (ser_date, 7, 10) .. string.sub (ser_date, 4, 5) .. string.sub (ser_date, 1, 2)

end

message (tostring (serverDate ()) .. "_" .. tostring (serverTime ()))
 
Цитата
Sergey Gorokhov написал:
в терминале версии 7.16 добавлена функция os.sysdate, позволяющая получить локальное время с точностью до микросекунд
обнаружил, что полученные из os.sysdate миллисекунды/микросекунды прирастают неравномерно, скачкообразно
ниже сравнил вывод sysdate.ms с os.clock()
версия QUIK 8.12.0.41
Код
function trace(level, msg)
   local sysdate = os.sysdate()
   local local_t = ("%02d:%02d:%04d %02d:%02d:%02d.%03d"):format(
         sysdate.day, sysdate.month, sysdate.year, sysdate.hour, sysdate.min, sysdate.sec, sysdate.ms)
   local _, clock_frac = math.modf(os.clock())
   local ms = ("%d"):format(math.floor(clock_frac*1000))

   local file = io.open(getScriptPath() .. "\\testSysDate.txt", "a")
   file:write(("%s %s [%s] : %s\n"):format(local_t, ms, level, msg))
   file:flush()
   file:close()
end

function testSysDate()
   for i = 0,getNumberOf("classes") - 1 do
      local code = getItem("classes", i).code
      trace("info", "Class " .. code)
   end
end
function main() testSysDate() end
вывод
Скрытый текст

28:03:2021 02:00:46.358 228 [info] : Class PSAU
28:03:2021 02:00:46.358 236 [info] : Class PSBB
28:03:2021 02:00:46.358 242 [info] : Class PSSU
..
28:03:2021 02:00:46.389 260 [info] : Class TQBR
28:03:2021 02:00:46.389 265 [info] : Class TQDE
28:03:2021 02:00:46.389 272 [info] : Class TQOB
...
389 - sysdate.ms
272 - fractional part of os.clock() -- milliseconds precision

видно, что вывод os.clock() гораздо точнее
 
Иван, добрый день!

Данное поведение обусловлено, дополнительным вызовом функции конвертации, в которой происходит округление миллисекунд, в os.sysdate().
Это корректное поведение в сравнении этих двух функций.
 
Roman Azarov,  os.sysdate напрямую использует системный таймер, который на Windows по умолчанию имеет точность ~16 миллисекунд.
 
Артем, добрый день!

Повторимся, в os.sysdate дополнительно происходит вызов функции конвертации, приводящей к округлению.
 
Цитата
sysdate

Функция возвращает системные дату и время с точностью до микросекунд.


Цитата
Roman Azarov написал:
Данное поведение обусловлено, дополнительным вызовом функции конвертации, в которой происходит округление миллисекунд, в os.sysdate().
Это как? Что во что конвертируется и по каким правилам округляется?
Надо делать так, как надо. А как не надо - делать не надо.
 
Старатель, добрый день!

В примере пользователя Иван речь идет именно о миллисекундах.
os.sysdate в отличие от os.clock вызывает в довесок к winapi'шной GetSystemTimeAsFileTime ещё и конвертацию через FileTimeToSystemTime. В последней и происходит округление миллисекунд.
 
Roman Azarov, в моем предыдущем примере точности до микросекунд не потребовалось. Но, все же это частный случай.
Тот же тест с микросекундами + статистика
Скрытый текст
вывод:
Скрытый текст
'sysdate.mcs' step-up:               'sysdate.mcs' step-up:               'sysdate.mcs' step-up:
 max     15644                        max     17826                        max     15640
 min     15603                        min     3049                         min     1065
 mean    15622.769231                 mean    13450.000000                 mean    12378.941176
Сейчас уже лучше видно, что os.sysdate имеет реальную точность ~16 msec +/-, как и было отмечено выше уже.

Цитата
Roman Azarov написал:
os.sysdate в отличие от os.clock вызывает в довесок к winapi'шной GetSystemTimeAsFileTime ещё и конвертацию через FileTimeToSystemTime. В последней и происходит округление миллисекунд.
т.е. пока получается, что реализация в полной мере не соответствует заявленному поведению в документациии
в документации нет примечания, что есть определенная погрешность в результате, выдаваемом функцией
 
Иван, добрый день!

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

Документация QLua касательно функции os.sysdate будет дополнена в одной из очередных версий ПО.
Приносим извинения за причиненные неудобства.
Страницы: 1
Читают тему
Наверх