|
Вопрос # 5 370/ вопрос открыт / |
|
Здравствуйте!
Проблема, вероятно, не из-за БД, а из-за говнокода, но всё может быть. Мне требуется сравнить 2 даты - одна из MonthCalendar, другую вытаскиваю из Access в переменную типа TDate. И на сравнение MonthCalender1.Date=AccessDate никакой реакции, хотя обе даты "29.05.2011". Только если поставить MonthCalender1.Date>=AccessDate, но это не подходит. Возиожно, дело в том, что Аксесс хранит ещё и время? Хотя это вряд ли
 |
Вопрос задал: 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 (статус: 2-ой класс), 4 июня 2011, 07:15 [#23]:
а SQL-запросом никак не решается вопрос сравнения? я так понял нужно выбрать из БД какую-то запись с нужной датой и работать с ней. Я бы кинул на форму TADOQuery и вытаскивал в него нужные записи.
|
|
nickel-j (статус: Посетитель), 4 июня 2011, 16:13 [#24]:
corban: ну, без TADOQuery вообще никуда - я только им и пользуюсь. А насчёт запроса - вполне возможно, просто у меня конструкция громоздкая - получится на каждое срабатывание таймера перебирать все записи и не по одному разу. А так я предварительно собираю их поля в массив типа запись, а потом по таймеру сравниваю уже значения массива с датой от TMonthcalendar
|
|
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 (статус: 2-ой класс), 7 июня 2011, 12:11 [#27]:
а че таймер срабатывает каждую миллисекунду? в массив-то он выгружает чето-там, значит и запрос должен успеть отработать
|
|
bugmenot (статус: 3-ий класс), 7 июня 2011, 17:31 [#28]:
Цитата (Вадим К):
Мы же сравниваем две даты, а не просто два числа. Цитата (Вадим К):
тип TDate - это обычное вещественное число. А их просто так сравнивать на равенство
Сам себе оппонент :-) Только выводом почему-то получилась точность 2 часа 24 минуты.
Цитата (Мережников Андрей):
функцией для сравнения дат: CompareDate() Там внутри тот же Trunc, который недостающую наносекунду превратит в сутки.
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
|
Мережников Андрей (статус: Абитуриент), 7 июня 2011, 17:39 [#29]:
Цитата (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 (статус: 3-ий класс), 7 июня 2011, 19:31 [#32]:
Цитата (Мережников Андрей):
азартно обсуждается проблема округления, что как-то забылся первоначальный вопрос
Потому что проблема интересная, с учётом того, что в дельфях тип TDateTime является основным средством работы с датой-временем.
А первоначальный вопрос довольно скучен.
Цитата (Мережников Андрей):
не храниться значение времени точнее секунды. Так что рассуждение на модную ныне тему нано - в данном случае совсем не надо
Зачем тогда запрашивал пример; если он оказался проигнорирован? А ведь из него следует, что проблема не в значащих цифрах, а в округлении вниз. См. тж. http://tsya.ru/
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
|
Мережников Андрей (статус: Абитуриент), 7 июня 2011, 20:09 [#33]:
Цитата (bugmenot):
Зачем тогда запрашивал пример; если он оказался проигнорирован?
спрашивал пример, имеющий отношение к реальной работе с БД. Если решается задача, в которой важна точность до микро- (нано-) секунд, то, как правило, в ней не учитывается количество дней. О том, что разработчики Delphi не предполагали использование типа TDateTime для отображения времени с такой точностью, говорит список функций для работы с данным типом.
|
|
bugmenot (статус: 3-ий класс), 7 июня 2011, 21:57 [#34]:
Цитата (Мережников Андрей):
пример, имеющий отношение к реальной работе с БД
Это делается SQL запросом и в общем-то на этом месте и наступает конец истории.Цитата (Мережников Андрей):
TDateTime для отображения времени с такой точностью
Опять отображение!
В настоящее время дни занимают только 16 бит мантиссы и отказ от них не повысит точность намного.
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
Страницы: [« Предыдущая] [1] [2]
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|