Форум программистов, компьютерный форум, киберфорум
Delphi: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
Кратк. - сест. тал.
 Аватар для Vit@L
87 / 51 / 4
Регистрация: 13.03.2008
Сообщений: 543

Не работает Locate через Timer

06.08.2019, 12:52. Показов 1792. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!
БД - Firebird. В ней есть некая таблица, в которой, есть поле "REMAINDERDATA" - тип: DateTime. Существует так же запись в этой таблице, в которой данное поле равно к примеру: 06.08.2019 15:00:00. На форме есть таймер с интервалом 1000, который каждю секунду выполняет такой код:
Delphi
1
2
3
4
5
Query1.Locate('REMAINDERDATA', date+time, [loCaseInsensitive, loPartialKey]);
if Query1.['REMAINDERDATA']=date+time then
   begin
      Вывести форму-напоминалку;
   end;
Но тут проблема. При совпадении даты и времени ничего не происходит, даже курсор в DBGrid'e не перемещается на нужную запись. Но если этот же код вставить к примеру в код нажатия кнопки, то все работает.
В чем может быть проблема?
Вместо "date+time" пробовал писать "now", результат тот же.
Заранее благодарен.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
06.08.2019, 12:52
Ответы с готовыми решениями:

Не работает процедура Locate
не работает процедура....когда на едит пишу он должен покажывать слова в дбгрид вооот код procedure TForm4.sEdit1Change(Sender:...

Locate работает некорректно
Вот фрагмент кода, при нажатии на кнопку выводит ошибку, что делать? if DM.ADOTable4.Locate('unit_name', VarArrayOf(), ) then ...

Не работает метод Locate
Не осуществляется поиск данных в поле Edit и не выдает никакую ошибку. помогите пожалуйста)

12
1076 / 989 / 340
Регистрация: 07.08.2012
Сообщений: 2,790
06.08.2019, 14:19
Цитата Сообщение от Vit@L Посмотреть сообщение
то все работает
Есть сомнение в этом утверждении, если судить по коду.
- в коде синтаксическая описка: Query1.['REMAINDERDATA'] - компилятор такую конструкцию не пропустит.

Если по сути вопроса. Да, суммарное значение функций Date+Time то же что и функция Now, но вероятность совпадения значений, которые находятся в таблице базы и тех, которые возвращают "now" ничтожно мала из-за того,что даже если дата и время совпадут, то это совпадение, скорее всего, придется на промежуток между срабатываниями событий по таймеру. Что, вероятно, и происходит.

Еще напомню, что метод Locate возвращает булевское значение True, если находит вхождение. Это к тому, что можно не делать последующее сравнение.
К тому же, для типа данных, связанных с датами и временем, флаги в этой функции не работают.

Может быть нужно хранить дату и время отдельно. Тогда проверка упрощается: сначала проверяется совпадение на дату, затем, если такое совпадение есть на время, но без использования секунд. Т.е. время хранить в виде часов и минут.

P.S. в FB нет типа DateTime (а тип, который может хранить одновременно дату и время называется TIMESTAMP).
0
Кратк. - сест. тал.
 Аватар для Vit@L
87 / 51 / 4
Регистрация: 13.03.2008
Сообщений: 543
06.08.2019, 15:28  [ТС]
Цитата Сообщение от Скандербег Посмотреть сообщение
Query1.['REMAINDERDATA']
Это я в форуме ошибся. Конечно, же у меня там нет точки.

Добавлено через 12 минут
Цитата Сообщение от Скандербег Посмотреть сообщение
Может быть нужно хранить дату и время отдельно. Тогда проверка упрощается: сначала проверяется совпадение на дату, затем, если такое совпадение есть на время, но без использования секунд. Т.е. время хранить в виде часов и минут.
Дуло в том, что cxScheduler так хранит дату и время.

Цитата Сообщение от Скандербег Посмотреть сообщение
в FB нет типа DateTime
Сорри, база не FB, а Absolute Database, а там именно тип DateTime.
0
1076 / 989 / 340
Регистрация: 07.08.2012
Сообщений: 2,790
06.08.2019, 15:42
Цитата Сообщение от Vit@L Посмотреть сообщение
cxScheduler так хранит дату и время
Как бы этот компонент не хранил дату/время, кто мешает "изъять" из него значение и убрать секунды, которые портят дело и сравнивать значения без этих не нужных секунд.
Ведь при срабатывании события таймера проверка происходит за какие-то миллисекунды и гарантии, что в базе будут значения именно этого мгновения нет никакой.
Выход здесь один: убрать секунды (в базе и в текущем моменте) и сравнивать только дату, часы и минуты.
За одну минуту события таймера, которых будет десятки, должны "поймать" нужное значение даты/времени.
0
Кратк. - сест. тал.
 Аватар для Vit@L
87 / 51 / 4
Регистрация: 13.03.2008
Сообщений: 543
06.08.2019, 16:14  [ТС]
Что-то я совсем запутался, сейчас пытаюсь откинуть секунды и миллисекунды, от конкретного времени с помощью decodetime, а он зараза, все равно сам секунды подставляет в конце и записывает их в таблицу. Как ни крути, все равно время в таблицу пишется такого вида: 12:00:00
Как быть?
0
1076 / 989 / 340
Регистрация: 07.08.2012
Сообщений: 2,790
06.08.2019, 16:47
Если в базу пишутся секунды и они всегда нулевые (12:10:00), то это как раз то что надо. Сравнение такого времени с текущим, где секунды тоже будут отброшены будет корректным.

Если же в базу пишутся секунды не нулевые (12:15:16), то время, скорее всего, надо будет записывать в виде часов и минут. Может быть в отдельных полях. Это позволит более гибко подходить к реализации проверок.
У меня в напоминалке сделано именно так: даты, часы и минуты в отдельных полях (последние в числовых типах). Собрать из таких значений время типа TDateTime никаких проблем не вызывает.
0
Модератор
 Аватар для D1973
9910 / 6447 / 2455
Регистрация: 21.01.2014
Сообщений: 27,365
Записей в блоге: 3
06.08.2019, 17:37
Vit@L, вообще сравнивать действительные числа на точное равенство - занятие бесперспективное, о чем Вы, без сомнения, уже неоднократно слышали. Тип TDateTime - ни что иное, как такое вот число с плавающей точкой где целая часть числа отвечает за дату, дробная - за время. Так что надо плясать именно отсюда - не проверять дату/время на точное совпадение, а проверять на попадание значения типа TDateTime из БД в некий ограниченный временной интервал...
0
Кратк. - сест. тал.
 Аватар для Vit@L
87 / 51 / 4
Регистрация: 13.03.2008
Сообщений: 543
06.08.2019, 21:17  [ТС]
Цитата Сообщение от Скандербег Посмотреть сообщение
Если в базу пишутся секунды и они всегда нулевые (12:10:00), то это как раз то что надо.
Да, всегда именно 00 (нули)
Цитата Сообщение от D1973 Посмотреть сообщение
Так что надо плясать именно отсюда - не проверять дату/время на точное совпадение, а проверять на попадание значения типа TDateTime из БД в некий ограниченный временной интервал...
Если честно, не совсем Вас понял. Может примерчик какой есть?
0
1076 / 989 / 340
Регистрация: 07.08.2012
Сообщений: 2,790
06.08.2019, 22:22
Лучший ответ Сообщение было отмечено Vit@L как решение

Решение

Цитата Сообщение от Vit@L Посмотреть сообщение
Да, всегда именно 00 (нули)
Тогда Locate отменяется.
А для проверки на совпадение с текущим временем нужно использовать SQL запрос (другим Query), в котором
значения поля "REMAINDERDATA" нужно сравнивать с переменной типа TDateTime, которая будет принимать текущие дату/время, но в значении которой не будет секунд.
Что-то в этом роде:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var
  DateT : TDateTime;
  AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond : Word;
begin
  DecodeDateTime(Now, AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond);
  DateT := EncodeDateTime(AYear, AMonth, ADay, AHour, AMinute, 0, 0);
        //строки выше можно оформить одной функцией
 
  Query2.SQL.Text := 'select * from tttt where REMAINDERDATA <= :DT';
  Query2.ParamByName('D').Value := DateT;
  Query2.Open;
  if not Query2.Eof then
    //cообщение о наступлении события
end;
Такая проверка должна сработать и в событии таймера, интервал в которого 1 сек.

Добавлено через 12 минут
Предложенный запрос, не будет правильно работать, т.к. вынужден вытаскивать и те данные, которые давно прошли по времени.
Поэтому его надо усовершенствовать с использованием диапазона (как, собственно, предлагает D1973)
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var
  DateB, DateE : TDateTime;
  AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond : Word;
begin
  DecodeDateTime(Now, AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond);
  DateE := EncodeDateTime(AYear, AMonth, ADay, AHour, AMinute, 0, 0);
  DateB := IncMinute(DateB, -1);  //диапазон в одну минут, но это лишь для примера, можно и больше
 
  Query2.SQL.Text := 'select * from tttt where REMAINDERDATA >= :DB and REMAINDERDATA <= :DE'; 
       //можно использовать и between, если поддерживается СУБД
  Query2.ParamByName('DB').Value := DateB;
  Query2.ParamByName('DE').Value := DateE;
  Query2.Open;
  if not Query2.Eof then
    //cообщение о наступлении события
end;
1
Кратк. - сест. тал.
 Аватар для Vit@L
87 / 51 / 4
Регистрация: 13.03.2008
Сообщений: 543
06.08.2019, 22:55  [ТС]
Скандербег, Спасибо большое. Только немного пришлось изменить код.
1. В запросе вместо "<= :DT" исправил на "= :DT" иначе, он мне каждую секунду выдает напоминание события которое уже прошло.
2. В "DateT := EncodeDateTime(AYear, AMonth, ADay, AHour, AMinute, 0, 0);" все же добавил еще секунды, иначе то же что и в первом варианте выдает напоминание каждую секунду пока не наступит следующая минута.

И в 9-й строке, Вы имели ввиду не "D", а "DT", так как в запросе указан параметр :DT, но это ерунда, у всех бывают оЧепятки.


Еще раз, ОГРОМНОЕ спасибо!!!
0
1076 / 989 / 340
Регистрация: 07.08.2012
Сообщений: 2,790
06.08.2019, 23:12
Цитата Сообщение от Vit@L Посмотреть сообщение
он мне каждую секунду выдает напоминание события которое уже прошло.
Ну да, это так. Поэтому запрос исправлен в другом (следующем) фрагменте кода, где он модифицирован, чтобы убрать эту проблему проверкой диапазона времени, а не на точное совпадение.
0
Кратк. - сест. тал.
 Аватар для Vit@L
87 / 51 / 4
Регистрация: 13.03.2008
Сообщений: 543
07.08.2019, 15:36  [ТС]
Всем большое спасибо! Все работает.
Только вот еще проблемка. У меня программа сворачивается в трей. И если при срабатывании события (в это время у меня открывается форма с напоминанием) программа была свернута, то все, восстановить ее потом невозможно, она не реагирует на двойной клик по значку в трее. Завершить можно только через Диспетчер задач. Но если программу не сворачивать в трей, а просто на панель задач, то все работает на УРА.
А если использовать компонент TJVDesktopAlert (это всякие красивые формочки-напоминания), то вообще при срабатывании события и при свернутой программе в трей ничего не показывается, а возникает Access Violation, и после программа тоже не может восстановиться из трея.
Никак это нельзя решить?

Добавлено через 1 час 20 минут
Скандербег, и, кстати, второй вариант тоже каждую секунду выводит сообщение о наступлении события, пока не добавишь секунды.

Добавлено через 40 минут
В общем только после такого изменения, стало работать как надо:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var
   DateB, DateE: TDateTime;
   AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word;
begin
   DecodeDateTime(Now, AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond);
   DateE := EncodeDateTime(AYear, AMonth, ADay, AHour, AMinute, ASecond, 0);
   DateB := IncSecond(DateE, -1);  
 
   QCheck.Close;
   QCheck.SQL.Text := 'select * from Organizer where REMAINDERDATA >= :DB and REMAINDERDATA <= :DE';
       //можно использовать и between, если поддерживается СУБД
   QCheck.ParamByName('DB').Value := DateB;
   QCheck.ParamByName('DE').Value := DateE;
   QCheck.Open;
   if not QCheck.Eof then frmReminder.ShowModal;
end;
0
Кратк. - сест. тал.
 Аватар для Vit@L
87 / 51 / 4
Регистрация: 13.03.2008
Сообщений: 543
07.08.2019, 22:33  [ТС]
С треем проблему решил. Вместо RzTrayIcon использую JVTrayIcon, он все отлично отрабатывает, и сообщение показывает и главную форму восстанавливает.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.08.2019, 22:33
Помогаю со студенческими работами здесь

Не работает Locate в составном поле
Здравствуйте уважаемые эксперты, проблема следующая, в проекте присутствует запрос вида SELECT , ,+'-'+ +'-'+...

ClientDataSet.Locate не работает с кириллицей
Строка ClientDataSet.Locate('UL_NAME', (Edit1.Text), ); не ищет русские символы в текстовом поле UL_NAME, просто их игнорирует. Цифры...

Объясните пожалуйста, как работает метод Locate?
Всем доброго времени суток. Есть БД Access, подключен к ней AdoConnection + AdoDataSet. Необходимо реализовать функцию поиска по БД, решил...

Поиск в БД через Locate без учета регистра
В чем может быть ошибка, поиск чувствителен к регистру и ищет если только полностью информацию вводить. Прописывал вот так: ...

Почему-то Locate по текстовому полю не работает при использовании AfterScroll
Здравствуйте. Имеется база в Access'е. Состоит из трех полей: поле счетчика и двух текстовых. Добавляется запись через команду SQL...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru