Текущий архив: 2004.10.10;
Скачать: CL | DM;
Вниз
Почему то упорно не работает UDF Найти похожие ветки
← →
S@shka © (2004-09-15 02:59) [0]function GetNextHour (var CurrentHour : TDateTime) : PChar; cdecl; export
const
onehour = 1/24;
var
t : TDateTime;
temp : String;
begin
t := CurrentHour + oneHour;
temp := FormatDateTime ("dd.mm.yyyy hh",t);
temp := temp + ":00:20";
temp := FormatDateTime ("dd.mm.yy hh:nn:ss",CurrentHour);
Result := malloc (length(temp) + 1);
StrPCopy (Result,temp);
end;
и InterBase описана как
DECLARE EXTERNAL FUNCTION F_NEXTHOUR
TIMESTAMP
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT "GetNextHour" MODULE_NAME "as.dll"
на любой запрос вида
select f_nexthour ("15.09.2004 01:00:01") from RDB$database
получаем
30.12.1899 01:00:20
Не понимаю - что не так???
← →
Fay © (2004-09-15 04:18) [1]Иди на ibase.ru. Найдёшь там инфу о написании UDF.
Обратишь внимание, что
1) IB/FB не знают, что есть TDateTime
2) Использование тобой переменной типа String ничем не оправдано.
← →
Digitman © (2004-09-15 08:29) [2]
> S@shka © (15.09.04 02:59)
см. [1]
IB-совместимые системы используют совершенно иной формат представления даты/времени
кр.того, malloc() нежелательно (а вскоре и недопустимо будет) использовать хотя бы по соображениям кроссплатформенности ... для аллокации памяти под возвращаемый рез-т следует использовать ib_util_malloc() в составе поставляемой штатно в дистрибутиве системы библ-ки ib_utils.dll
← →
S@shka © (2004-09-15 10:39) [3]А как же время то передавать ???
Мне нужно в UDF передать TDateTime
и вернуть из него TDateTime + один час с округлением
до ровных часов назад
Т.е.
Input = "15.09.2004 01:25:05"
Output = "15.09.2004 02:00:00";
← →
Digitman © (2004-09-15 11:34) [4]uses
IBHeader
const
MSecsPerDay10 = MSecsPerDay * 10; // миллисекунд в сутках * 10
IBDateDelta = 15018; // разница в днях между датами Delphi и IBDatabase
//внутренняя ф-ция для преобразования даты/времени из формата IB в формат Делфи
function QuadToDate(ibd: TISC_QUAD): TDateTime;
begin
Result:= ibd.gds_quad_high - IBDateDelta + ibd.gds_quad_low / MSecsPerDay10;
end;
//внутренняя ф-ция для преобразования даты/времени из формата Делфи в формат IB
function DateToQuad(d: TDateTime): TISC_QUAD;
var
Days: Integer;
begin
Days:= Trunc(d);
Result.gds_quad_high:= Days + IBDateDelta;
Result.gds_quad_low:= Trunc((d - Days) * MSecsPerDay10);
end;
function GetNextHour (var IBDateTime : TISC_QUAD) : PChar; cdecl;
...
var
DelphiDate : TDateTime;
...
begin
DelphiDateTime := QuadToDate(IBDateTime);
....
end;
← →
Виталий Панасенко (2004-09-15 11:52) [5]А current_timestamp никак прикрутить нельзя и без UDF обойтись? Или я не совсем понял проблему ?
← →
S@shka © (2004-09-15 12:50) [6]Да проблема то вообщем сформулирована была
нужно выполнить следующее округление до ровных часов вперед
Т.е.
Input = "15.09.2004 01:25:05"
Output = "15.09.2004 02:00:00";
а с UDF или нет все равно,
мне казалось что в UDF будет проще реализовать данную задачу
← →
Digitman © (2004-09-15 13:08) [7]
> S@shka © (15.09.04 12:50) [6]
мне не оч понятно, зачем результат возвращать в виде строки ...
чем оправдано это требование ? почему не вернуть рез-т в виде того же TISC_QUAD (timestamp) ? а потому ж при реальной необходимости форматнуть этот рез-т в строку, представляющую дату/время ? ведь если параметр типа TISC_QUAD и рез-т того же типа, то это позволит обойтись без выделения памяти под рез-т !
← →
S@shka © (2004-09-15 13:22) [8]Yes
именно в TimeStamp результат и нужен
я же так понимаю при возвращении результата как TIMESTAMP
необходимо выделять память так как передавать надо по ссылке
а как правильно это слелать я пока не нашел.
А вообще зачем это все нужно (может это проще можно сделать и не нужно никаких UDF брать)
Имеем табличку
Param Time Value
1 12.05.2004 11:00:01 1
1 12.05.2004 11:01:01 1
1 12.05.2004 11:02:11 1
1 12.05.2004 11:03:36 1
1 12.05.2004 12:00:01 1
И мне нужно определить, например, сумму значений
по каждому часу т.е.
time between 11:00 12:00 и т.д.
то есть для данного набора должен был выдать
1 12.05.2004 12:00:00 4
1 12.05.2004 13:00:00 1
← →
Digitman © (2004-09-15 14:02) [9]
> я же так понимаю при возвращении результата как TIMESTAMP
> необходимо выделять память так как передавать надо по ссылке
нет, выделять память в случаях, когда размер параметра совпадает с размером результата, совершенно необязательно
дело в том, что при передаче факт.параметра ИБ формирует временную его копию в своей памяти и передает в UDF ссылку на него
этот врем.параметр будет уничтожет только после того как ИБ получит результат вызова UDF, чем с успехом можно и воспользоваться, записав результат в область памяти, отведенную под врем.параметр
function GetNextHour (var IBDateTime : TISC_QUAD) : PISC_QUAD; cdecl;
function ProcessInputParameter(dt: TDateTime): TDateTime;
begin
... //здесь формируешь рез-т привычным образом и по нужному алгоритму
end;
begin
Result := @IBDateTime; //результат передаем по ссылке на область памяти, занятую вх.параметром
Result^ := DateToQuad(ProcessInputParameter(QuadToDate(IBDateTime)));
end;
DECLARE EXTERNAL FUNCTION F_NEXTHOUR
TIMESTAMP /* параметр по дифолту передается по ссылке */
RETURNS TIMESTAMP /* результат по дифолту так же возвращается по ссылке */
ENTRY_POINT "GetNextHour" MODULE_NAME "as.dll"
← →
Digitman © (2004-09-15 14:13) [10]
> S@shka © (15.09.04 13:22) [8]
ФБ свежих релизов позволяет в запросах группировки по результатам, возвращаемым из UDF
так что для твоей задачи лучше было бы возвращать из UDF значение часа в этом дне (см. ф-цию DecodeTime)
тогда в запросе можно будет использовать
... GROUP BY GetTimestampHour(SomeIBTimeStampValue)
← →
S@shka © (2004-09-15 14:49) [11]Большое спасибо.
Страницы: 1 вся ветка
Текущий архив: 2004.10.10;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.029 c