Вести с полей

Сегодня начал писать новый код для адаптера EntityFrameworkCore. Попытался начать 🙂

Нужно соорудить транслятор System.DateTime.AddDays(double) в SQL.

Сначала надо посмотреть как Firebird переварит double значение:

… а переваривает он его не так как ожидалось 🙂


По-моему в IBProvider уже есть транслятор в DATEADD. Из какой-то ODBC-функции.

И сдается мне, в тот раз (это было 11 лет назад) мы прошляпили эту засаду с округлением.

7 комментариев

hvlad  on 9 ноября, 2018

Ты удивлён, что кол-во дней приводится к целому ?
А кто-то где-то обещал другое ?
Посмотри как в MSSQL работает DATEADD.

Или я не так понял твою печаль ? 😉

hvlad  on 9 ноября, 2018

Кстати, для того, чтобы показать запрос и результат — не нужно снимать видео. Это, как минимум, не даёт скопировать запрос и повторить, не показывает всей нужной инф-ции на одном экране (нужно постоянно листать видео).
Такое вот мнение.

Dmitry Kovalenko  on 9 ноября, 2018

Привет.

System.DateTime.AddDays(double)

Parameters
value
Double
A number of whole and fractional days. The value parameter can be negative or positive.

Returns
DateTime
An object whose value is the sum of the date and time represented by this instance and the number of days represented by value.

Remarks
This method does not change the value of this DateTime. Instead, it returns a new DateTime whose value is the result of this operation.

The fractional part of value is the fractional part of a day. For example, 4.5 is equivalent to 4 days, 12 hours, 0 minutes, 0 seconds, 0 milliseconds, and 0 ticks.


Печали нет. Наоборот 🙂

FirebirdSql.EntityFrameworkCore.Firebird.BLA-BLA-BLA.FbDateAddTranslator

Исходя из текущего поведения сервера, AddDays нужно конвертировать в что-то типа:

DATEADD(MILLISECOND,86400000*CAST(1.5 AS DOUBLE PRECISION),"r"."COL_TIMESTAMP")


Насчет видео. Это у меня появилась новая игрушка 🙂

Dmitry Kovalenko  on 9 ноября, 2018

Насчет MSSQL, это ты точно заметил. Но они не округляют.

Запрос «select DATEADD(DAY, 1.6,CONVERT(datetime,’01.01.2000′))» возвращает «2000-01-02 00:00:00.000».

В своем EFCore провайдере они это тоже не учитывают 🙂


Чтобы два раза не вставать, посмотрел как себя ведет PG.

Запрос «select CAST(‘01.01.2000’ AS timestamp) + ‘1.5 day'» возвращает «2000-01-02 12:00:00».

Соответственно, его EFCore провайдер конвертирует AddDays корректно.

Симонов Денис  on 16 ноября, 2018

В PG для этого есть отдельный тип — интервал времени. ИХМО в Firebird такой тоже не помешал бы, а то с новыми фишками в оконных функциях нужно придумывать велосипеды чтобы прибавлять и вычитать от текущей строки что-то отличное от дней SUM(money) OVER(ORDER BY BYDATE RANGE BETWEEN 3 PRECEDING AND 3 FOLLOWING)

Dmitry Kovalenko  on 18 ноября, 2018

Вот жеж, едрёна матрёна:

«select DATEADD(MILLISECOND,1.5,CAST(‘2018-10-09 00:00:00’ AS TIMESTAMP)) from dual»

возвращает

«09.10.2018 00:00:00.0015»

Dmitry Kovalenko  on 18 ноября, 2018

Причина негодования в последнем случае заключается в том, что DateTime.AddMilliseconds округляет до целого.

DateTime.AddMilliseconds(Double) Method:

Parameters

value

Double

A number of whole and fractional milliseconds. The value parameter can be negative or positive. Note that this value is rounded to the nearest integer.

Leave a Comment