unit TimeFunctions;

interface
uses Windows, MMSystem, SysUtils;

//Системный таймер Windows
function GetSystemWorkTime(): String;

//Мультимедийный таймер
function timeGetMaxPeriod(): Cardinal;
function timeGetMinPeriod(): Cardinal;
function timeSetTimerPeriod(period: Cardinal): Boolean;
function timeRestoreTimerPeriod(): Boolean;
//Функция timeGetTime используется напрямую из модуля MMSystem
//function timeGetTime: DWORD; stdcall;

//Аппаратный таймер высокой частоты
function hwTimerGetFreq(): Int64;
function hwTimerGetCounter(): Int64;
function hwCounterToTimeStr(counter: Int64): String;

implementation
var
  lastPeriod: Cardinal; //Используется для восстановления состояния
                        //мультимедийного таймера

function GetSystemWorkTime(): String;
var
  ticks: DWORD;
  hh, mm, ss: Cardinal;
begin
  //Получаем количество миллисекунд с момента старта системы
  ticks := GetTickCount();
  //Переводим в секунды
  ticks := ticks div 1000;
  //Получаем количество часов, минут, секунд
  hh := ticks div 3600;
  Dec(ticks, hh * 3600);
  mm := ticks div 60;
  Dec(ticks, mm * 60);
  ss := ticks;

  GetSystemWorkTime := IntToStr(hh) + ':' +
                       IntToStr(mm) + ':' + IntToStr(ss);
end;

//Получение максимального периода таймера (мс)
function timeGetMaxPeriod(): Cardinal;
var
  time: TTimeCaps;
begin
  timeGetDevCaps(Addr(time), SizeOf(time));
  timeGetMaxPeriod := time.wPeriodMax;
end;

//Получение минимального периода таймера (мс)
function timeGetMinPeriod(): DWORD;
var
  time: TTimeCaps;
begin
  timeGetDevCaps(Addr(time), SizeOf(time));
  timeGetMinPeriod := time.wPeriodMin;
end;

//Установка периода таймера (мс) перед началом измерения
function timeSetTimerPeriod(period: Cardinal): Boolean;
begin
  if timeBeginPeriod(period) = TIMERR_NOERROR then
  begin
    //Сохраним значение для восстановления состояния таймера
    lastPeriod := period;
    timeSetTimerPeriod := True;
  end
  else
    //Неудача
    timeSetTimerPeriod := False;
end;

//Восстановление периода таймета (обязательно)
function timeRestoreTimerPeriod(): Boolean;
begin
  if timeEndPeriod(lastPeriod) = TIMERR_NOERROR then
    timeRestoreTimerPeriod := True
  else
    timeRestoreTimerPeriod := False;
end;

//Получениеч астоты аппаратного таймера (0 - ошибка)
function hwTimerGetFreq(): Int64;
var
  freq: Int64;
begin
  if QueryPerformanceFrequency(freq) <> FALSE then
    hwTimerGetFreq := freq
  else
    hwTimerGetFreq := 0; //Ошибка
end;

//Получение значения счетчика срабатываний аппаратного таймера (0 - ошибка)
function hwTimerGetCounter(): Int64;
var
  freq: Int64;
begin
  if QueryPerformanceCounter(freq) <> FALSE then
    hwTimerGetCounter := freq
  else
    hwTimerGetCounter := 0; //Ошибка
end;

//Функция рассчитывает время, необходимое для заданного количества
//обновления аппаратного счетчика и переводит его в текстовый формат
function hwCounterToTimeStr(counter: Int64): String;
var
  time: Int64;
  hh, mm, ss: Cardinal;
begin
  //Рассчитываем время, соответствующее count
  //обновлениям аппаратного счетчика
  time := counter div hwTimerGetFreq();
  //Перевод в текстовый формат с выделение часов,
  //минут и секунд
  hh := time div 3600;
  Dec(time, hh * 3600);
  mm := time div 60;
  Dec(time, mm * 60);
  ss := time;

  hwCounterToTimeStr := IntToStr(hh) + ':' +
                     IntToStr(mm) + ':' + IntToStr(ss);
end;

end.
