Функция, обратная win.FileTimeToLocalFileTime Topic is solved

Столкнулись с проблемой в использовании макросов? Здесь можно получить помощь.
User avatar
buniak_a_h
Posts: 4236
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 643 times
Contact:

Функция, обратная win.FileTimeToLocalFileTime

Post by buniak_a_h »

Здравствуйте, уважаемые Знатоки!
Проблема следующая:
в history.db дата-время хранится в виде bit64-userdata-числа. Как его в читабельную форму я, вроде, нашёл. Теперь хочется уметь преобразовывать "наоборот" (из даты-времени получать число). Например, для формулирования фильтра (SQL-запроса). Всё упирается в отсутствие в таблице win функции, обратной FileTimeToLocalFileTime. Хотя в системе описана функция LocalFileTimeToFileTime. Вопрос к авторам (к сожалению, главный - Shmuel - самоустранился :-( ): как обойти данное ограничение?
Shmuel
Posts: 6820
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 528 times

Функция, обратная win.FileTimeToLocalFileTime

Post by Shmuel »

Есть разные варианты решения. Простейший, наверное, такой:

Code: Select all

function LocalFileTimeToFileTime (ftime)
  return 2*ftime - win.FileTimeToLocalFileTime(ftime)
end
User avatar
buniak_a_h
Posts: 4236
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 643 times
Contact:

Функция, обратная win.FileTimeToLocalFileTime

Post by buniak_a_h »

Shmuel, а двоечка тут - это случайно не часовой пояс?
Я нашёл какой-то прокто-логичный способ:

Code: Select all

local function _Dt() -- Вычисляю поправку на часовой пояс и летнее/зимнее время (на сегодня!)
  local a1 = win.GetSystemTimeAsFileTime()
  local a2 = win.FileTimeToLocalFileTime(a1)
  local a3 = (a2 - a1)
  return a3
end
local function LocalFileTimeToFileTime(ftime)
  return ftime - Dt()
end
Вроде, работает…
2useven10
Posts: 5209
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Функция, обратная win.FileTimeToLocalFileTime

Post by 2useven10 »

Лучше с преобразованиями Local <-> System справляются функции ...TzSpecificLocalTime...
FileTimeToLocalFileTime(...) -> SystemTimeToTzSpecificLocalTime(NULL, ...)
LocalFileTimeToFileTime(...) -> TzSpecificLocalTimeToSystemTime(NULL, ...)
К сожалению, они отсутствуют в win...
придётся вызывать через ffi.
Last edited by 2useven10 on Wed 08 Jun, 2022 06:40, edited 1 time in total.
User avatar
buniak_a_h
Posts: 4236
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 643 times
Contact:

Функция, обратная win.FileTimeToLocalFileTime

Post by buniak_a_h »

2useven10, да я уж видел … Но я не настолько знаю современный СИ, да ещё с ffi, чтобы писать что-то через них.
Ладно, как-то работает (и, вроде, правильно) - и ладно.
Всем спасибо.
2useven10
Posts: 5209
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Функция, обратная win.FileTimeToLocalFileTime

Post by 2useven10 »

buniak_a_h wrote: Wed 08 Jun, 2022 06:53 как-то работает (и, вроде, правильно) - и ладно.
Для текущего времени, или если таймзона без перехода на зимнее/летнее время будет работать.
User avatar
buniak_a_h
Posts: 4236
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 643 times
Contact:

Функция, обратная win.FileTimeToLocalFileTime

Post by buniak_a_h »

2useven10 wrote: Wed 08 Jun, 2022 07:07 Для текущего времени, или если таймзона без перехода на зимнее/летнее время…
Я понимаю. Ну, вместо win.GetSystemTimeAsFileTime можно использовать win.SystemTimeToFileTime(systime). Поскольку мне это нужно для преобразования даты-времени из текстового вида (dd.MM.yyyy hh:mm:ss), то заполнить структуру systime возможность имеется.
2useven10
Posts: 5209
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Функция, обратная win.FileTimeToLocalFileTime

Post by 2useven10 »

buniak_a_h wrote: Wed 08 Jun, 2022 07:40 Я понимаю.
Судя по тексту, нет.

Насколько я помню, все функции преобразования времени Win32 API и рантайм, кроме TzSpecific, применяют текущее временное смещение при конвертации любого времени.
И соответственно (если есть разница) летом будет ошибка при преобразовании зимних времён, а зимой летних. TzSpecific используют смещение того времени, которое они конвертируют.
Last edited by 2useven10 on Wed 08 Jun, 2022 09:36, edited 1 time in total.
User avatar
buniak_a_h
Posts: 4236
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 643 times
Contact:

Функция, обратная win.FileTimeToLocalFileTime

Post by buniak_a_h »

2useven10!
  1. Это не проверить из-за отсутствия перехода на летнее/зимнее время.
  2. Такие функции правильно переводят текстовое время в LONG LONG (или что там в history.db указывается) и обратно:

    Code: Select all

    local function NtoD(a) -- из числа в дд.мм.гггг чч:мм:сс
      local aDt = win.FileTimeToSystemTime( win.FileTimeToLocalFileTime( tonumber(a)/10000 ) )
      return ('%.2d.%.2d.%.4d %.2d:%.2d:%.2d'):format(aDt.wDay, aDt.wMonth, aDt.wYear, aDt.wHour, aDt.wMinute, aDt.wSecond)
    end -- function NtoD
    ---------------------------------------
    local function StoDt(s) -- Перевод из текста в структуру tSystemTime (вспомогательная)
      return {
        wDay = tonumber(s:sub(1,2));
        wMonth = tonumber(s:sub(4,5));
        wYear = tonumber(s:sub(7,10));
        wHour = tonumber(s:sub(12,13));
        wMinute = tonumber(s:sub(15,16));
        wSecond = tonumber(s:sub(18,19));
      }
    end -- function StoDt
    ---------------------------------------
    local function Dlt(dt) -- вычисление добавки на дату dt (вот! здесь и учитывается переход на летнее/зимнее время, если есть)
      if type(dt) == 'string' then
        dt = StoDt(dt)
      end
      local a = win.SystemTimeToFileTime(dt)
      return win.FileTimeToLocalFileTime(a) - a
    end -- function Dlt
    ---------------------------------------
    local function DtoN(s) -- преобразование даты из строки вида dd.MM.yyyy hh:mm:ss в числовое значение
      local dt = StoDt(s)  -- 1234567890123456789
      return (win.SystemTimeToFileTime(dt) - Dlt(dt)) * 10000
    end
    
    Проверяется просто:

    Code: Select all

    local ss = '31.08.2022 12:45:15' -- или любую другую дату
    far.Show('28:', ss, NtoD(DtoN(ss)))
    
Last edited by buniak_a_h on Wed 08 Jun, 2022 09:41, edited 1 time in total.
2useven10
Posts: 5209
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Функция, обратная win.FileTimeToLocalFileTime

Post by 2useven10 »

buniak_a_h,
  1. Отмотайте время назад, когда таймзоны были (или было UTC+4, а не UTC+3 как сейчас)
  2. Ваша проверка ничего не показывает (смещение сейчас и 31.08.22 одно и то же)
Проверять можно на времени файла:
Берёте файл с датой до 26.10.2014 или даже до 2011 года (2010 зима, 2010 лето) на NTFS томе.
Получаете его FILETIME, печатаете дату вашими функциями и сравниваете с тем что даёт FAR.
User avatar
buniak_a_h
Posts: 4236
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 643 times
Contact:

Функция, обратная win.FileTimeToLocalFileTime

Post by buniak_a_h »

  1. Я просто не помню, когда отменили переход. Такие подойдут: 31.01.2010 12:45:15 и 31.07.2010 12:45:15 ? Если да, то проверку они проходят.
  2. Я и так знаю, что не показывала без перехода на зимнее-летнее время. См. (1).
  3. На самом деле меня интересует не время файла, а время, которое пишется в history.db в поле time. Оно в 10 000 раз больше. Я не знаю, как его вычисляет ФАР, но зато я легко могу проверить: засечь время, когда набрал команду и нажал Enter, преобразовал в текст функцией NtoD (в тексте) - убедился, что преобразовывает нормально. Ну и по DtoN и обратно по NtoD - убедился, что всё правильно.
User avatar
buniak_a_h
Posts: 4236
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 643 times
Contact:

Функция, обратная win.FileTimeToLocalFileTime

Post by buniak_a_h »

Похоже, функция win.FileTimeToLocalFileTime тоже не учитывает переход на летнее/зимнее время для тех дат, когда он (переход) был. Разница между датой и ею же после win.FileTimeToLocalFileTime всегда одинаковая (даже для 1990 года!) - 10800000 Что, в общем, объяснимо: не хранить же всю историю исканий А.М. !
Last edited by buniak_a_h on Wed 08 Jun, 2022 10:35, edited 2 times in total.
2useven10
Posts: 5209
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Функция, обратная win.FileTimeToLocalFileTime

Post by 2useven10 »

Это одно и то же время, просто у Shmuel время обрезается до миллисекунд,
а в FILETIME (и видимо в history.db) время в сотнях наносекунд.
То что DtoN и NtoD у вас обратимы не подтверждает их правильную работу,
просто там будет одна и та же ошибка.

Но всё это будет актуально для таймзон с зимним и летним временем.
В истории у вас скорее всего не будет записей 8+ летней давности.
Если вас результат устраивает, пусть будет так.
Last edited by 2useven10 on Wed 08 Jun, 2022 11:37, edited 1 time in total.
2useven10
Posts: 5209
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Функция, обратная win.FileTimeToLocalFileTime

Post by 2useven10 »

buniak_a_h wrote: Wed 08 Jun, 2022 10:33 Похоже, функция win.FileTimeToLocalFileTime
Да, именно об этом и шла речь. TzSpecific работают правильнее.
Last edited by 2useven10 on Wed 08 Jun, 2022 11:03, edited 1 time in total.
User avatar
buniak_a_h
Posts: 4236
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 643 times
Contact:

Функция, обратная win.FileTimeToLocalFileTime

Post by buniak_a_h »

2useven10 wrote: Wed 08 Jun, 2022 11:02 То что DtoN и NtoD у вас обратимы не подтверждает их правильную работу
Зато я точно знаю время, когда выдал команду (с точностью до секунды). А затем лезу в history.db и преобразовываю записанное там время в текс функцией NtoD. А вот это я уже могу проверить. И с точностью до секунды функция работает правильно. Меня эта точность вполне устраивает.
Post Reply

Return to “Нужна помощь”