Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 5 370

/ вопрос открыт /

Здравствуйте!
Проблема, вероятно, не из-за БД, а из-за говнокода, но всё может быть. Мне требуется сравнить 2 даты - одна из MonthCalendar, другую вытаскиваю из Access в переменную типа TDate. И на сравнение MonthCalender1.Date=AccessDate никакой реакции, хотя обе даты "29.05.2011". Только если поставить MonthCalender1.Date>=AccessDate, но это не подходит. Возиожно, дело в том, что Аксесс хранит ещё и время? Хотя это вряд ли

nickel-j Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: nickel-j (статус: Посетитель)
Вопрос отправлен: 3 июня 2011, 14:04
Состояние вопроса: открыт, ответов: 2.

Ответ #1. Отвечает эксперт: min@y™

Всё понятно. TDate, TTime и TDateTime - это тот же Double. Сравнивать на равенство такие вещи нельзя, т.к. дробные числа хранятся в памяти в двоичном виде с погрешностью. Так что, если надо узнать, равны ли 2 даты, то:

if Trunc(Date1) = Trunc(Date2)
  then ...

Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 3 июня 2011, 14:09
Оценка за ответ: 5

Ответ #2. Отвечает эксперт: Вадим К

Здравствуйте, nickel-j!
Посмотрите внимательней, что такое тип TDate - это обычное вещественное число. А их просто так сравнивать на равенство нельзя.
В Вашем случае наиболее правильно сделать где то так
abs(MonthCalender1.Date - AccessDate) < 0.1
вместо проверки на равенство. константу 0.1 подбираете самостоятельно, Если там будут только даты записаны, то думаю 0.1 --- 0.01 будет предостаточно. разница в 1 - это один день.
А вот Trunc, как советует min@y™, может давать неверный результат в некоторых случаях. Ведь число 5 может быть записано как 4.999999 и trunc сделает с него 4. а может быть записано в виде 5.0000001 и trunc сделает 5.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 3 июня 2011, 14:14
Оценка за ответ: 5


Мини-форум вопроса

Всего сообщений: 34; последнее сообщение — 7 июня 2011, 21:57; участников в обсуждении: 6.

Страницы: [« Предыдущая] [1] [2]

Вадим К

Вадим К (статус: Академик), 3 июня 2011, 23:23 [#21]:

Цитата (bugmenot):

Грубо, см. Math.SameValue для оценки бесконечно малых

Если хоть чуточку подумаете, то поймете, что не так. Мы же сравниваем две даты, а не просто два числа.
Галочка "подтверждения прочтения" - вселенское зло.
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 4 июня 2011, 06:42 [#22]:

Если есть желание заморачиваться с преобразованиями, то проще воспользоваться функцией DateOf() и не гадать что-же получиться в результате округления.
Или воспользоваться готовой функцией для сравнения дат: CompareDate(). Описание обеих можно найти в help.
corban

corban (статус: 2-ой класс), 4 июня 2011, 07:15 [#23]:

а SQL-запросом никак не решается вопрос сравнения? я так понял нужно выбрать из БД какую-то запись с нужной датой и работать с ней. Я бы кинул на форму TADOQuery и вытаскивал в него нужные записи.
nickel-j

nickel-j (статус: Посетитель), 4 июня 2011, 16:13 [#24]:

corban: ну, без TADOQuery вообще никуда - я только им и пользуюсь. А насчёт запроса - вполне возможно, просто у меня конструкция громоздкая - получится на каждое срабатывание таймера перебирать все записи и не по одному разу. А так я предварительно собираю их поля в массив типа запись, а потом по таймеру сравниваю уже значения массива с датой от TMonthcalendar
corban

corban (статус: 2-ой класс), 6 июня 2011, 09:15 [#25]:

.... А так я предварительно собираю их поля в массив типа запись, а потом по таймеру сравниваю уже значения массива с датой от TMonthcalendar

а зачем? Делаешь что-то типа этого:

with ADOQuery1 do
begin
Close;
SQL.Clear;
SQL.Append('SELECT *');
SQL.Append('FROM tablica_access');
SQL.Append('WHERE AccessDate='+DateToStr(MonthCalender1.Date);
Open;
end;

вешаешь на таймер и у тебя все записи с нужной датой в одной куче. Зачем массив нужен я не понял...
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 6 июня 2011, 19:52 [#26]:

to corban - уверен, что запрос успеет отработать за время между срабатываниями таймера?
corban

corban (статус: 2-ой класс), 7 июня 2011, 12:11 [#27]:

а че таймер срабатывает каждую миллисекунду? в массив-то он выгружает чето-там, значит и запрос должен успеть отработать
bugmenot

bugmenot (статус: 3-ий класс), 7 июня 2011, 17:31 [#28]:

Цитата (Вадим К):

Мы же сравниваем две даты, а не просто два числа.

Цитата (Вадим К):

тип TDate - это обычное вещественное число. А их просто так сравнивать на равенство

Сам себе оппонент :­-­) Только выводом почему-то получилась точность 2 часа 24 минуты.

Цитата (Мережников Андрей):

функцией для сравнения дат: CompareDate()
Там внутри тот же Trunc, который недостающую наносекунду превратит в сутки.
виконання програми розпочинається з того самого мiсця, де призупинилося.

Мережников Андрей

Мережников Андрей (статус: Абитуриент), 7 июня 2011, 17:39 [#29]:

Цитата (bugmenot):

который недостающую наносекунду превратит в сутки.

пример в студию.
bugmenot

bugmenot (статус: 3-ий класс), 7 июня 2011, 18:01 [#30]:

с микросекундой, для наносекунды - по индукции
procedure TForm11.FormCreate(Sender: TObject);
const
  uSecPerDay = MSecsPerDay * UInt64(1000);
  uSec = 1 / uSecPerDay;
var
  A, B: TDate;
begin
  A := EncodeDate(1952, 10, 7);  // дата взята исключительно для лулзов
  B := A;
  B := B - uSec;
  Assert(SameDateTime(A, B), 'PASSES');
  Assert(SameDate(A, B), 'FAILS');
end;
виконання програми розпочинається з того самого мiсця, де призупинилося.

Мережников Андрей

Мережников Андрей (статус: Абитуриент), 7 июня 2011, 18:25 [#31]:

так азартно обсуждается проблема округления, что как-то забылся первоначальный вопрос - сравнение даты, хранящейся в БД Access и значением даты в MonthCalendar. А следовало бы вспомнить, что в Access не храниться значение времени точнее секунды. Так что рассуждение на модную ныне тему нано - в данном случае совсем не надо.
bugmenot

bugmenot (статус: 3-ий класс), 7 июня 2011, 19:31 [#32]:

Цитата (Мережников Андрей):

азартно обсуждается проблема округления, что как-то забылся первоначальный вопрос

Потому что проблема интересная, с учётом того, что в дельфях тип TDateTime является основным средством работы с датой-временем.
А первоначальный вопрос довольно скучен.

Цитата (Мережников Андрей):

не храниться значение времени точнее секунды. Так что рассуждение на модную ныне тему нано - в данном случае совсем не надо

Зачем тогда запрашивал пример; если он оказался проигнорирован? А ведь из него следует, что проблема не в значащих цифрах, а в округлении вниз. См. тж. http://tsya.ru/
виконання програми розпочинається з того самого мiсця, де призупинилося.

Мережников Андрей

Мережников Андрей (статус: Абитуриент), 7 июня 2011, 20:09 [#33]:

Цитата (bugmenot):

Зачем тогда запрашивал пример; если он оказался проигнорирован?

спрашивал пример, имеющий отношение к реальной работе с БД. Если решается задача, в которой важна точность до микро- (нано-) секунд, то, как правило, в ней не учитывается количество дней. О том, что разработчики Delphi не предполагали использование типа TDateTime для отображения времени с такой точностью, говорит список функций для работы с данным типом.
bugmenot

bugmenot (статус: 3-ий класс), 7 июня 2011, 21:57 [#34]:

Цитата (Мережников Андрей):

пример, имеющий отношение к реальной работе с БД

Это делается SQL запросом и в общем-то на этом месте и наступает конец истории.

Цитата (Мережников Андрей):

TDateTime для отображения времени с такой точностью

Опять отображение!
В настоящее время дни занимают только 16 бит мантиссы и отказ от них не повысит точность намного.
виконання програми розпочинається з того самого мiсця, де призупинилося.

Страницы: [« Предыдущая] [1] [2]

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 16 мая 2026, 15:53
Выполнено за 0.04 сек.