Угу, а если мне ничего более и не требуется?Slavik писал(а):Согласись, что разницу между этими двумя значениями можно считать часом лишь приближённо на "бытовом" уровне
Работа с полями TimeStamp в FB
-
- Сообщения: 144
- Зарегистрирован: 16 фев 2006, 22:36
Доброго времени суток!
C вычитанием тоже интересная вещь получается - см. http://groups.google.com/group/ru-fireb ... 463f430b62
Видимо, потому что timestamp в 3-м диалекте - это NUMERIC(18,9).Slavik писал(а):Если к значению типа timestamp прибавлять h/23.(9) (где h - целое количество часов от 1 до 23), то точность вычислений растёт с увеличением количества девяток, и наилучший (но всё же не точный) результат достигается при девяти девятках, а дальше точность падает в полном соответствии с предыдущими изысканиями о точности вычисления 1/23.(9).
C вычитанием тоже интересная вещь получается - см. http://groups.google.com/group/ru-fireb ... 463f430b62
Это объясняет, почему достигается полная точность (до одной десятитысячной секунды) при добавлении к timestamp'у часов в виде выражения h/24.(0) с десятью и более нулями после точки.Кузнецов Евгений писал(а):Видимо, потому что timestamp в 3-м диалекте - это NUMERIC(18,9).
Но это не объясняет падение точности вычисления выражения 1/23.(9) при увеличении количества девяток после девяти штук.
Эта ветка мне на многое открыла глаза. Я тоже был в заблуждении и думал, что разница между timestamp'ами вычисляется точно. И согласен, что точную разницу между timestamp'ами можно получить в десятитысячных секуды:Кузнецов Евгений писал(а):C вычитанием тоже интересная вещь получается - см. http://groups.google.com/group/ru-fireb ... 463f430b62
Правда я бы приводил к bigint или numeric(18,0).Кузнецов Евгений (по ссылке) писал(а):Разумеется, можно, сделать CAST((end_date-start_date)*86400*10000 AS INTEGER) и дальше использовать его в расчетах
А вот дальнейшие рассуждения мне непонятны. Чем это некрасиво? Ведь если имеем точную разницу в десятитысячных секунды, то чтобы получить её же, например, в целых секундах достаточно разделить полученное целое значение десятитысячных на 10000 (дробная часть при этом отбрасывается). Если же надо получить разницу в дробных секундах (как при вычитании двух значений типа time) -- то делим на 10000.0000.
-
- Сообщения: 144
- Зарегистрирован: 16 фев 2006, 22:36
Да, этого я тоже не понимаю - результат 1/23.9999999999 вроде бы должен иметь точность NUMERIC(18,10), но этого не получаемSlavik писал(а):Но это не объясняет падение точности вычисления выражения 1/23.(9) при увеличении количества девяток после девяти штук.
Почитайте до конца - это неправильно, нужно еще округлять. Говоря о некрасивости, я имел в виду, что при вычислении разницы в часах одним запросом будет нагромождение CAST'овSlavik писал(а):Правда я бы приводил к bigint или numeric(18,0). А вот дальнейшие рассуждения мне непонятны. Чем это некрасиво?
В общем, вот окончательный вариант в виде процедуры - http://www.delphikingdom.com/asp/answer ... swer=50989
Зачем? Ведь округление уже происходит в выраженииКузнецов Евгений писал(а):Почитайте до конца - это неправильно, нужно еще округлять.
CAST((end_date-start_date)*86400*10000 AS INTEGER)
Проведя тест, на разнице в датах от 0 до 9999 десятитысячных секунды, я не обнаружил ни одной ошибки в этом округлении. Зачем ещё какие-то округления и танцы с +-0.5?
Выполнил запрос:Кузнецов Евгений писал(а):В общем, вот окончательный вариант в виде процедуры - http://www.delphikingdom.com/asp/answer ... swer=50989
Код: Выделить всё
select * from DATE_DIFF('2007-08-22 00:00:01.0010', '2007-08-22 00:00:00.0000')
DAYS = 0; HOURS = 0; MINUTES = 0; SECONDS = 1; MILLISECONDS = 11
Неговоря уже о том, что странно обзывать десятитысячные миллисекундами, но результат неверен: вместо 10 получили 11. Думаю, это из-за +0.5.
Попутно я обнаружил, что вычитание двух timestamp'ов (Date1-Date2), если Date1<Date2, не всегда даёт верный результат (например, если значения отличаются на одну десятитысячную, разница будет почему-то равна нулю ).
Поэтому лучше всегда вычитать из большей даты меньшую:
Код: Выделить всё
cast((case when Date1<Date2 then -(Date2-Date1) else Date1-Date2 end)
*(24*60*60*10000) as bigint)
-
- Сообщения: 144
- Зарегистрирован: 16 фев 2006, 22:36
Доброго времени суток!
Видимо, что-то в двойке правили, я писал для 1.5.4Slavik писал(а):Проведя тест, на разнице в датах от 0 до 9999 десятитысячных секунды, я не обнаружил ни одной ошибки в этом округлении. Зачем ещё какие-то округления и танцы с +-0.5?
В 1.5 все работает нормально.Slavik писал(а):Выполнил запрос:и получил следующий результат:Код: Выделить всё
select * from DATE_DIFF('2007-08-22 00:00:01.0010', '2007-08-22 00:00:00.0000')
DAYS = 0; HOURS = 0; MINUTES = 0; SECONDS = 1; MILLISECONDS = 11
Да, это я заметил, но править не сталSlavik писал(а):Неговоря уже о том, что странно обзывать десятитысячные миллисекундами
-
- Сообщения: 144
- Зарегистрирован: 16 фев 2006, 22:36
To Slavik
Посмотрел еще - при вычитании дат в FB 2 происходит округление, а в 1.5 - отбрасывание разрядов
в FB 2.02.12897 возвращает 19.008,
в 1.5.4 - 18.144
Любопытно, но
в FB 2.0.2.12897 возвращает -18.144 (т.е. округления в этом случае не происходит, поэтому у Вас и теряется миллисекунда)
Что-то тут не так. Подождем, пока в эту ветку разработчики заглянут
Посмотрел еще - при вычитании дат в FB 2 происходит округление, а в 1.5 - отбрасывание разрядов
Код: Выделить всё
select (CAST('2007-08-22 00:00:00.0019' AS TIMESTAMP)-
CAST('2007-08-22 00:00:00.0000' AS TIMESTAMP))*86400*10000
from rdb$database
в 1.5.4 - 18.144
Любопытно, но
Код: Выделить всё
select (CAST('2007-08-22 00:00:00.0000' AS TIMESTAMP)-
CAST('2007-08-22 00:00:00.0019' AS TIMESTAMP))*86400*10000
from rdb$database
Что-то тут не так. Подождем, пока в эту ветку разработчики заглянут
-
- Сообщения: 144
- Зарегистрирован: 16 фев 2006, 22:36
Доброго времени суток!
To Slavik
К счастью, в 2.1 Beta 2 разработчики это поправили: http://tracker.firebirdsql.org/browse/CORE-1428
To Slavik
К счастью, в 2.1 Beta 2 разработчики это поправили: http://tracker.firebirdsql.org/browse/CORE-1428
Осталось дождаться релиза.Кузнецов Евгений писал(а):К счастью, в 2.1 Beta 2 разработчики это поправили: http://tracker.firebirdsql.org/browse/CORE-1428