Форум программистов, компьютерный форум, киберфорум
Наши страницы
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 20, средняя оценка - 4.85
Crystallon
1 / 1 / 0
Регистрация: 20.06.2011
Сообщений: 55
#1

TTimer отстает от отсчета времени в PHP - Delphi

23.06.2011, 20:48. Просмотров 2764. Ответов 12
Метки нет (Все метки)

Для меня удивительно что такое возможно но компонент TTimer считает что секунда должна быть медленнее чем она на самом деле есть... Ситуация такая: при запуске программы время синхронизируется с веб сервером(программа получает от сервера его время в секундах, заносит в переменную типа Integer, включается таймер с промежутком 1000 миллисекунд и таймер каждый раз при срабатывании добавляет к этой переменной 1) (крайне необходимо чтобы время было синхронизировано и разница между временем на веб сервере и временем в программе составляла не более 15 секунд). Ну я разумеется подумал что даже если есть какое-то отличие то рассинхронизация времени на 15 секунд займет по меньшей времени месяц непрерывной работы программы что уже не страшно, но оказалось что это возможно буквально за час(точно не скажу но точно меньше 2 часов). Может быть я что-то делаю не так как нужно? Или это все таки трабла самого компонента? Если второе то есть ли какие-либо альтернативные варианты?
Если это важно: разница между временем сервера и программы за 2 часа выросла с 15 секунд до 2 минут(каждую минуту отстает почти на секунду, просто ужс).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.06.2011, 20:48
Я подобрал для вас темы с готовыми решениями и ответами на вопрос TTimer отстает от отсчета времени в PHP (Delphi):

Ttimer смена интервала через заданный промежуток времени
Доброго времени суток. Такая задачка: Нужно заставить таймер срабатывать...

Сколько времени пройдет до следующего события OnTimer при изменении св-ва TTimer.Interval
если в цыкле таймера установить новый интервал, сколько времени пройдет до...

Нужен проверенный алгоритм отсчета времени
Люди добрые проблема вот в чем. Написал прогу построения графиков TChart. При...

Продолжение отсчета времени после перезагрузки (запомнить время при закрытии приложения)
Приветствую уважаемые! Такая проблемка... Есть таймер, он отсчитывает время с...

Ttimer
Расскажите, как работать с таймером в Delphi. Если я в интервале задам 50. И...

TTimer
Что и чему нужно присваивать чтобы уменьшать размер текста при помощи интервала...

12
obscurant
13 / 13 / 2
Регистрация: 08.09.2010
Сообщений: 26
23.06.2011, 21:52 #2
а вы в обработчике таймера перед действием отключаете его?

Delphi
1
2
3
4
5
procedure TForm1.Timer1Timer(Sender: TObject);
begin
    Timer1.Interval:=0; //Отключаем таймер
    ... //Некоторое действие
end;
1
Arcor
4816 / 1817 / 380
Регистрация: 20.11.2009
Сообщений: 5,776
Записей в блоге: 1
23.06.2011, 22:42 #3
быть не должно, может программа большая и работает неправильно, то есть грузятся другие процессы, и от этого тормозится сам подсчет времени ???
1
Mawrat
12821 / 5729 / 1700
Регистрация: 19.09.2009
Сообщений: 8,807
23.06.2011, 22:50 #4
Crystallon, TTimer не предназначен для точного счёта времени. Его предназначение - порождение событий с заданным временным интервалом, к которому не предъявляются требования точности. Для точного отслеживания времени надо использовать показания аппаратного таймера.
Таким образом, точный счётчик времени можно построить на основе TTimer и дополнительного кода, читающего показания аппаратного таймера.
Например, можно сделать так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
var
  //Начальный момент времени.
  TimeStart : TTime = 0;
  //Отслеживаемый интервал.
  Period : TTime = 0;
  //Время прошедшее от начального момента.
  TimeCur : TTime = 0;
 
//Запуск/перезапуск таймера.
procedure TForm1.Button1Click(Sender: TObject);
begin
  //Выключаем таймер.
  Timer1.Enabled := False;
  //Интервал таймера.
  //Timer1.Interval := 1000; //1000 миллисекунд.
 
  //Значение отслеживаемого периода, заданное в секундах, переводим
  //в формат данных типа TTime (TDateTime).
  Period := StrToIntDef(Edit1.Text, 0) / (24 * 60 * 60);
  //Определяем текущее время.
  TimeStart := Time;
  //Показываем начальное время.
  Label1.Caption := FormatDateTime('hh:nn:ss', 0);
  //Включаем таймер.
  Timer1.Enabled := True;
end;
 
//Останов таймера.
procedure TForm1.Button2Click(Sender: TObject);
begin
  //Выключаем таймер.
  Timer1.Enabled := False;
  //Обнуляем показание времени в строке.
  Label1.Caption := FormatDateTime('hh:nn:ss', 0);
end;
 
//Обработка тиков таймера.
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  //Узнаём сколько времени прошло.
  TimeCur := Time - TimeStart;
 
  //Отслеживаем момент, когда пройдёт заданный интервал.
  if TimeCur >= Period then begin
    //Останавливаем таймер.
    Timer1.Enabled := False;
    //Показываем конечное значение времени.
    Label1.Caption := FormatDateTime('hh:nn:ss', Period);
    //Сообщение.
    ShowMessage('Заданный период истёк.');
    //Выходим.
    Exit;
  end;
 
  //Показыавем сколько времени прошло.
  Label1.Caption := FormatDateTime('hh:nn:ss', TimeCur);
end;
Точность такого таймера равна:
<погрешность аппаратного таймера за истёкший период> + TTimer.Interval.
1
Миниатюры
TTimer отстает от отсчета времени в PHP  
Вложения
Тип файла: rar Таймер с прямым счётом.rar (170.8 Кб, 54 просмотров)
Crystallon
1 / 1 / 0
Регистрация: 20.06.2011
Сообщений: 55
24.06.2011, 07:56  [ТС] #5
obscurant
Нет, не отключаю, но это могло быть причиной только если таймер бы спешил а не опаздывал, а так тут нет никакой связи...
Arcor
Да, программа большая, но нельзя перебирая варианты начинать с самого плохого(такого при котором ничего нельзя изменить) =)
Mawrat
Огромное спасибо.
0
Arcor
4816 / 1817 / 380
Регистрация: 20.11.2009
Сообщений: 5,776
Записей в блоге: 1
24.06.2011, 14:24 #6
а почему не брать время с компьютера постоянно,и через таймер просто его как бы обновлять?

---
Mawrat: Правильно - именно так и надо делать. В представленной выше программе применяется подобный подход. - Интервал отслеживается по системным часам, а TTimer обеспечивает перерасчёт и обновление информации на форме.
0
Crystallon
1 / 1 / 0
Регистрация: 20.06.2011
Сообщений: 55
24.06.2011, 17:51  [ТС] #7
Действительно...только сейчас нашлось время чтобы попробовать этот код, и только сейчас я узнал что он работает не так как мне нужно...то что можно сравнить разницу между серверным временем и временем клиентского ПК, найти разницу и в последствии ее прибавлять/вычитать к времени клиентского ПК чтобы получать сервеное время...это все конечно хорошо, вот только если пользователь по каким-угодно причинам изменит время в процессе работы программы будет уже не хорошо... не буду вдаваться в подробности, просто скажу что в моем случае соответствие времени сервера и клиента критично и если его не будет работа программы абсолютно невозможна =\ именно по этому мне нужно полностью независимое от внешних факторов время внутри программы.
0
Mawrat
12821 / 5729 / 1700
Регистрация: 19.09.2009
Сообщений: 8,807
24.06.2011, 20:51 #8
Цитата Сообщение от Crystallon Посмотреть сообщение
это все конечно хорошо, вот только если пользователь по каким-угодно причинам изменит время в процессе работы программы будет уже не хорошо...
...
именно по этому мне нужно полностью независимое от внешних факторов время внутри программы.
Это да - тот код, который я представил, зависит от показаний системных часов. А их значение пользователь может поменять.
Но есть ещё один способ - вот он обеспечит независимость. Чуть позже я напишу его. Он основан на работе с показаниями мультимедийного таймера.
---
Вот этот код:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
var
  //Начальный момент времени.
  TimeStart : TDateTime = 0;
  //Отслеживаемый интервал.
  Period : TDateTime = 0;
  //Время прошедшее от начального момента.
  TimeCur : TDateTime = 0;
 
//Переводит текущее показание мультимедийного таймера
//в формат TDateTime;
function GetTickCountTime : TDateTime;
begin
  Result := GetTickCount / (24 * 60 * 60 * 1000);
end;
 
//Запуск/перезапуск таймера.
procedure TForm1.Button1Click(Sender: TObject);
begin
  //Выключаем таймер.
  Timer1.Enabled := False;
  //Интервал таймера.
  //Timer1.Interval := 1000; //1000 миллисекунд.
 
  //Значение отслеживаемого периода, заданное в секундах, переводим
  //в формат данных типа TTime (TDateTime).
  Period := StrToIntDef(Edit1.Text, 0) / (24 * 60 * 60);
  //Определяем текущее время по мультимедийному таймеру.
  TimeStart := GetTickCountTime;
  //Показываем начальное время.
  Label1.Caption := FormatDateTime('hh:nn:ss', 0);
  //Включаем таймер.
  Timer1.Enabled := True;
end;
 
//Останов таймера.
procedure TForm1.Button2Click(Sender: TObject);
begin
  //Выключаем таймер.
  Timer1.Enabled := False;
  //Обнуляем показание времени в строке.
  Label1.Caption := FormatDateTime('hh:nn:ss', 0);
end;
 
//Обработка тиков таймера.
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  //Узнаём сколько времени прошло.
  TimeCur := GetTickCountTime - TimeStart;
 
  //Отслеживаем момент, когда пройдёт заданный интервал.
  if TimeCur >= Period then begin
    //Останавливаем таймер.
    Timer1.Enabled := False;
    //Показываем конечное значение времени.
    Label1.Caption := FormatDateTime('hh:nn:ss', Period);
    //Сообщение.
    ShowMessage('Заданный период истёк.');
    //Выходим.
    Exit;
  end;
 
  //Показыавем сколько времени прошло.
  Label1.Caption := FormatDateTime('hh:nn:ss', TimeCur);
end;
Здесь всё тоже самое, но только за основу взяты показания мультимедийного таймера. Это обеспечивает независимость от показаний системных (аппаратных) часов. Мультимедийный таймер отсчитывает количество миллисекунд, прошедшее от момента запуска операционной системы (Windows).
---
Выкладываю этот проект
1
Crystallon
1 / 1 / 0
Регистрация: 20.06.2011
Сообщений: 55
25.06.2011, 11:18  [ТС] #9
Да, пожалуй это идеальный вариант) винда сама ведет отсчет и при этом пользователь не может его нарушить =)
Спасибо.

Добавлено через 14 часов 6 минут
Подскажите пожалуйста, как перевести TDateTime в Integer?
0
Mawrat
12821 / 5729 / 1700
Регистрация: 19.09.2009
Сообщений: 8,807
25.06.2011, 13:31 #10
Цитата Сообщение от Crystallon Посмотреть сообщение
Подскажите пожалуйста, как перевести TDateTime в Integer?
TDateTime - этот тип является псевдонимом типа Double. Вот как он определён в модуле System:
Delphi
1
2
3
4
5
6
7
8
unit System;
...
interface
...
type
...
  TDateTime = type Double;
...
Устроен TDateTime так.
Переменная этого типа хранит количество суток. Причём, в целой части записано количество целых суток, а в дробной - часть суток.
Например:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var
  Dt : TDateTime;
begin
  //Нулевое время:
  Dt := 0;
  //Одни сутки:
  Dt := 1;
  //Двое суток:
  Dt := 2;
  //Двое с половиной суток, т. е.: двое суток и 12 часов:
  Dt := 2.5;
  //Двое суток и один час. Т. к., час равен 1/24 суток:
  Dt := 2 + 1/24;
  //Двое суток, один час и одна минута:
  Dt := 2 + 1/24 + 1/(24 * 60);
  //Двое суток, один час, одна минута и одна секунда:
  Dt := 2 + 1/24 + 1/(24 * 60) + 1/(24 * 60 * 60);
  //Двое суток, один час, одна минута, одна секунда и одна миллисекунда:
  Dt := 2 + 1/24 + 1/(24 * 60) + 1/(24 * 60 * 60) + 1/(24 * 60 * 60 * 1000);
end;
В модуле Controls определены также типы: TTime и TDate - они являются псевдонимами типа TDateTime и устроены точно также. Вот как они определены:
Delphi
1
2
3
4
5
6
7
8
9
10
unit Controls;
...
interface
...
type
...
  TDate = type TDateTime;
 
  TTime = type TDateTime;
...
В Delphi, для работы со временем, принято соглашение, что показания времени отсчитываются от момента: 30.12.1899 24:00:00:000. Т. е., если к переменной типа TDateTime применить какую-нибудь функцию работы с датами и временем, то значение этой переменной будет воспринято, как время, прошедшее от момента 30.12.1899 24:00:00:000. Причём, отрицательные значения имеют смысл, как время, оставшееся до наступления момента 30.12.1899 24:00:00:000.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
procedure TForm1.Button1Click(Sender: TObject);
var
  Dt : TDateTime;
begin
  Dt := 0;
  Memo1.Lines.Add('Dt := 0;');
  Memo1.Lines.Add('Нулевое время:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
  Memo1.Lines.Add('');
 
  Dt := -1;
  Memo1.Lines.Add('Dt := -1;');
  Memo1.Lines.Add('Минус одни сутки:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
  Memo1.Lines.Add('');
 
  Dt := -2;
  Memo1.Lines.Add('Dt := -2;');
  Memo1.Lines.Add('Минус двое суток:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
  Memo1.Lines.Add('');
 
  Dt := 1;
  Memo1.Lines.Add('Dt := 1;');
  Memo1.Lines.Add('Одни сутки:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
  Memo1.Lines.Add('');
 
  Dt := 2;
  Memo1.Lines.Add('Dt := 2;');
  Memo1.Lines.Add('Двое суток:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
  Memo1.Lines.Add('');
 
  Dt := 2.5;
  Memo1.Lines.Add('Dt := 2.5;');
  Memo1.Lines.Add('Двое с половиной суток:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
  Memo1.Lines.Add('');
 
  Dt := 2 + 1/24;
  Memo1.Lines.Add('Dt := 2 + 1/24;');
  Memo1.Lines.Add('Двое суток и один час. Т. к., час равен 1/24 суток:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
  Memo1.Lines.Add('');
 
  Dt := 2 + 1/24 + 1/(24 * 60);
  Memo1.Lines.Add('Dt := 2 + 1/24 + 1/(24 * 60);');
  Memo1.Lines.Add('Двое суток, один час и одна минута:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
  Memo1.Lines.Add('');
 
  Dt := 2 + 1/24 + 1/(24 * 60) + 1/(24 * 60 * 60);
  Memo1.Lines.Add('Dt := 2 + 1/24 + 1/(24 * 60) + 1/(24 * 60 * 60);');
  Memo1.Lines.Add('Двое суток, один час, одна минута и одна секунда:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
  Memo1.Lines.Add('');
 
  Dt := 2 + 1/24 + 1/(24 * 60) + 1/(24 * 60 * 60) + 1/(24 * 60 * 60 * 1000);
  Memo1.Lines.Add('Dt := 2 + 1/24 + 1/(24 * 60) + 1/(24 * 60 * 60 * 1000);');
  Memo1.Lines.Add('Двое суток, один час, одна минута, одна секунда и одна миллисекунда:');
  Memo1.Lines.Add(FormatDateTime('dd.mm.yyyy" / "hh:nn:ss:zzz', Dt));
end;
Программист, в своих целях, может наделять данные в переменных типа TDateTime другом смыслом. - Например, можно полагать, что переменная содержит время прошедшее не от 30.12.1899 24:00:00:000, а от какого-то другого момента. Например, в постах выше полагалось, что время отсчитывается от момента запуска таймера.
---
Чтобы найти список имеющихся в Delphi функций для работы с временем, надо открыть справку Delphi и на закладке "Предметный указатель" произвести поиск по фразе: "Datetime routines".
---
Чтобы найти сведения об управлении форматированием строк со сведениями о дате и времени, надо в справке Delphi на закладке "Поиск" произвести поиск по фразе: "Date-Time Format Strings".
Приведу здесь эти сведения:
Код
Date/Time format strings control the formatting of dates and times.

Description

Date-Time Format Strings specify the formatting of date-time values (such as TDateTime) when they are converted to strings. Date-Time Format Strings are passed to formatting routines (such as FormatDateTime), and are also used to set certain global variables (such as ShortDateFormat).

Date Time Format Strings are composed from specifiers that represent values to be inserted into the formatted string. Some specifiers (such as "d"), simply format numbers or strings. Other specifiers (such as "/") refer to locale-specific strings from global variables.

In the following table, specifiers are given in lower case. Case is ignored in formats, except for the "am/pm" and "a/p" specifiers.

Specifier	Displays
c	Displays the date using the format given by the ShortDateFormat global variable, followed by the time using the format given by the LongTimeFormat global variable. The time is not displayed if the date-time value indicates midnight precisely.
d	Displays the day as a number without a leading zero (1-31).
dd	Displays the day as a number with a leading zero (01-31).
ddd	Displays the day as an abbreviation (Sun-Sat) using the strings given by the ShortDayNames global variable.
dddd	Displays the day as a full name (Sunday-Saturday) using the strings given by the LongDayNames global variable.
ddddd	Displays the date using the format given by the ShortDateFormat global variable.
dddddd	Displays the date using the format given by the LongDateFormat global variable.
e	(Windows only) Displays the year in the current period/era as a number without a leading zero (Japanese, Korean and Taiwanese locales only).
ee	(Windows only) Displays the year in the current period/era as a number with a leading zero (Japanese, Korean and Taiwanese locales only).
g	(Windows only) Displays the period/era as an abbreviation (Japanese and Taiwanese locales only).
gg	(Windows only) Displays the period/era as a full name. (Japanese and Taiwanese locales only).
m	Displays the month as a number without a leading zero (1-12). If the m specifier immediately follows an h or hh specifier, the minute rather than the month is displayed.
mm	Displays the month as a number with a leading zero (01-12). If the mm specifier immediately follows an h or hh specifier, the minute rather than the month is displayed.
mmm	Displays the month as an abbreviation (Jan-Dec) using the strings given by the ShortMonthNames global variable.
mmmm	Displays the month as a full name (January-December) using the strings given by the LongMonthNames global variable.
yy	Displays the year as a two-digit number (00-99).
yyyy	Displays the year as a four-digit number (0000-9999).
h	Displays the hour without a leading zero (0-23).
hh	Displays the hour with a leading zero (00-23).
n	Displays the minute without a leading zero (0-59).
nn	Displays the minute with a leading zero (00-59).
s	Displays the second without a leading zero (0-59).
ss	Displays the second with a leading zero (00-59).
z	Displays the millisecond without a leading zero (0-999).
zzz	Displays the millisecond with a leading zero (000-999).
t	Displays the time using the format given by the ShortTimeFormat global variable.
tt	Displays the time using the format given by the LongTimeFormat global variable.
am/pm	Uses the 12-hour clock for the preceding h or hh specifier, and displays 'am' for any hour before noon, and 'pm' for any hour after noon. The am/pm specifier can use lower, upper, or mixed case, and the result is displayed accordingly.
a/p	Uses the 12-hour clock for the preceding h or hh specifier, and displays 'a' for any hour before noon, and 'p' for any hour after noon. The a/p specifier can use lower, upper, or mixed case, and the result is displayed accordingly.
ampm	Uses the 12-hour clock for the preceding h or hh specifier, and displays the contents of the TimeAMString global variable for any hour before noon, and the contents of the TimePMString global variable for any hour after noon.
/	Displays the date separator character given by the DateSeparator global variable.
:	Displays the time separator character given by the TimeSeparator global variable.
'xx'/"xx"	Characters enclosed in single or double quotes are displayed as-is, and do not affect formatting.
2
Crystallon
1 / 1 / 0
Регистрация: 20.06.2011
Сообщений: 55
25.06.2011, 20:08  [ТС] #11
Я хочу получить время в виде количества секунд от начала отсчета, аналогично тому как выдает функция time в PHP.
Простите за хреновую постановку вопроса.
0
Mawrat
12821 / 5729 / 1700
Регистрация: 19.09.2009
Сообщений: 8,807
25.06.2011, 20:29 #12
Одна секунда в формате TDateTime равна: 1 / (24 * 60 * 60). Поэтому, если задан некоторый временной интервал Dt в формате TDateTime, то количество секунд в нём равно:
CntSec = Dt / ( 1 / (24 * 60 * 60) ) = Dt * (24 * 60 * 60).
Соответственно, можно функцию написать:
Delphi
1
2
3
4
5
6
function GetSec(const aPeriod : TDateTime) : Int64;
const
  K = 24 * 60 * 60;
begin
  Result := Round( Int(aPeriod * K) );
end;
1
Crystallon
1 / 1 / 0
Регистрация: 20.06.2011
Сообщений: 55
26.06.2011, 11:15  [ТС] #13
Спасибо =)
Тему можно закрывать.
0
26.06.2011, 11:15
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.06.2011, 11:15
Привет! Вот еще темы с решениями:

Работа с TTimer
Добрый вечер. Помогите доделать прогу не могу освоить таймер. Задание у меня...

Не работает TTimer!
Всем привет. Сразу к проблеме. Таймер включается здесь: procedure...

TTimer + PaintBox
Задание выглядит так: нарисовать в делфи пятиугольник и с помощью TTimer...

Спецификация Компонента TTimer
Вот задался вопросом в какой момент выпоняеца событие OnTimer Поясняю Вот...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru