![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
IB 7.5 Как хр. процедуре в переменнной типа date обнулить время?
novill © (2007-01-09 16:16:00)сабж
Desdechado (2007-01-09 19:16:00) [41]Ega23 © (09.01.07 19:13) [21]
В 1 диалекте есть только DATE (он же TIMESTAMP в 3 диалекте).
В 3 диалекте есть отдельно DATE (просто дата) и TIME (просто время).
Ega23 (2007-01-09 19:13:00) [42]
> Нет, AFAIK. Там сложная упаковка даты-времени.
Подожди, это про timestamp. А datetime? Я просто очень давно с FB игрался, уже год не подходил, не помню нифига.
Desdechado (2007-01-09 19:08:00) [43]Ega23 © (09.01.07 19:01) [19]
> В то, что datetime в IB/FB/YA не ксатуется в число - я просто не верю.
Нет, AFAIK. Там сложная упаковка даты-времени.
{--- тип TIMESTAMP в InterBase ---}
T_ISC_DATE = LongInt;
T_ISC_TIME = DWord;
T_ISC_TIMESTAMP = record
timestamp_date: T_ISC_DATE;
timestamp_time: T_ISC_TIME;
end;
P_ISC_TIMESTAMP = ^T_ISC_TIMESTAMP;
{--- распакованный для удобства TIMESTAMP ---}
T_UNPACKED_TIMESTAMP = record
fraction: DWord; // доля секунды
second: Word; // 0..59
minute: Word; // 0..59
hour: Word; // 0..23
day: Word; // 1..31
month: Word; // 0..11
year: SmallInt; // calendar year minus 1900
end;
P_UNPACKED_TIMESTAMP = ^T_UNPACKED_TIMESTAMP;
// Calenders are divided into 4 year cycles: 3 Non-Leap years, and 1 leap year.
// Each cycle takes 365*4 + 1 == 1461 days.
// There is a further cycle of 100 4 year cycles.
// Every 100 years, the normally expected leap year is not present. Every 400 years it is.
// This cycle takes 100 * 1461 - 3 == 146097 days
// The origin of the constant 2400001 is unknown.
// The origin of the constant 1721119 is unknown.
// The difference between 2400001 and 1721119 is the number of days
// from 0/0/0000 to our base date of 11/xx/1858. (678882)
// The origin of the constant 153 is unknown.
//
// This whole routine has problems with ndates
// less than -678882 (Approx 2/1/0000).
{----- упаковка данных в TIMESTAMP -----}
// календарная дата в число дней от базовой даты
function encode_isc_date( nYear: SmallInt; nMonth: Word; nDay: Word ): T_ISC_DATE;
var
nCentury, nYearInCentury: SmallInt;
begin
if( nMonth > 2 ) then
nMonth := Word( nMonth - 3 )
else
begin
nMonth := Word( nMonth + 9 );
nYear := Word( nYear - 1 );
end;
nCentury := nYear div 100;
nYearInCentury := nYear mod 100;
result := LongInt( 146097*nCentury ) div 4 + LongInt( 1461*nYearInCentury ) div 4 +
( 153*nMonth + 2 ) div 5 + nDay + 1721119 - 2400001;
end;
// время + десятые доли миллисекунд
function encode_isc_time( var nTime: T_ISC_TIME; nHour: Word; nMinute: Word; nSecond: Word; nFraction: DWord ): Word;
begin
result := 0;
// корректность параметров
while( nSecond > 59 ) do
begin
Dec( nSecond, 60 );
Inc( nMinute );
end;
while( nMinute > 59 ) do
begin
Dec( nMinute, 60 );
Inc( nHour );
end;
while( nHour > 23 ) do
begin
Dec( nHour, 23 );
Inc( result ); // переполнение часов, сутки +1
end;
// утоптать
nTime := isc_time_seconds_precision *( ( nHour*60 + nMinute )*60 + nSecond ) +
T_ISC_TIME( nFraction div ( 100*1000 ) );
end;
// собственно компрессия в TIMESTAMP
procedure encode_isc_timestamp( const unp_ts: P_UNPACKED_TIMESTAMP; isc_ts: P_ISC_TIMESTAMP );
var
n: Word;
begin
isc_ts.timestamp_date := encode_isc_date( unp_ts.year, unp_ts.month, unp_ts.day );
n := encode_isc_time( isc_ts.timestamp_time, unp_ts.hour, unp_ts.minute, unp_ts.second, unp_ts.fraction );
Inc( isc_ts.timestamp_date, n );
end;
Ega23 (2007-01-09 19:01:00) [44]
> Но дело в том, что формат день.месяц.год (именно в такой
> последовательности и именно с таким разделителем) является
> "внутренним стандартом" IB/FB/YA
Да? Не знал. Спасибо, учту.
И тем не менее, datetime - суть число. Обнулить время - отбросить дробную часть. В Паскале - Trunc, в TSQL - прикастовать к int - это автоматом усечёт нули. В то, что datetime в IB/FB/YA не ксатуется в число - я просто не верю. Может не напрямую в int, а через промежуточный float, но это роли не меняет.
Desdechado (2007-01-09 18:59:00) [45]> Для третьего диалекта ещё проще
> select cast( TimestampValue as date) from rdb$database
Естественно. Здесь и спрашивать нечего, не то что отвечать.
> Кстати, у тебя ошибка в [10]
В чем?
> дело в том, что формат день.месяц.год (именно в такой последовательности и именно с таким разделителем)
> является "внутренним стандартом" IB/FB/YA
Ну-ну. Ты подставь туда минус, слэш, запятую, их комбинации и разглядишь их "стандарты". Может, когда-нибудь поймешь, чем чревато изменение недокументированного поведения "стандартов".
try (2007-01-09 18:50:00) [46]
> Ega23 © (09.01.07 18:28) [16]
Я понимаю твои сомнения.
Но дело в том, что формат день.месяц.год (именно в такой последовательности и именно с таким разделителем) является "внутренним стандартом" IB/FB/YA
Ega23 (2007-01-09 18:28:00) [47]
> С этого места поподробнее. Желательно с доказательными примерами.
С ib-диалектами знаком слабо, но коли ты кастуешь строку к дате, то нельзя забывать, что дата 02.03.2004 может означать как 2 марта 2004, так и 3 февраля 2004.
И если в том-же MS SQL набрать следующую строку
Select Convert(varchar(10), Cast('02.03.2004' as datetime), 104), то получим как раз 3 февраля, а не 2 марта.
Опять же, я не сильный знаток ib-диалекта, но очень сильно подозреваю, что в FB такая же фигня. А вот во что он прикастует по-умолчанию - будет зависеть от региональных настроек.
Сейчас под рукой сервера нет, дома обязательно проверю.
try (2007-01-09 18:17:00) [48]
> Desdechado © (09.01.07 17:58) [11]
> try (09.01.07 17:49) [9]Ты бы попробовал сначала, ага?
> Не первый раз уже такую пургу несешь...
Я попробовал. А ты? Что получилось?
try (2007-01-09 18:11:00) [49]
> Desdechado © (09.01.07 17:54) [10]
Для третьего диалекта ещё проще
select cast( TimestampValue as date) from rdb$database :)))
Кстати, у тебя ошибка в [10]
> Ega23 © (09.01.07 18:03) [12]
> Ты [4] внимательно читал, или как?
Конечно. Но ещё внимательней я читал вопрос автора.
И выходит [4] совсем не в кассу....
> Ega23 © (09.01.07 18:05) [13]
> > [3] от региональных настроек не зависит никоем образом.
> Невооружённым взглядом видно, что зависит.02.03.04 кастоваться
> по-разному будет.
С этого места поподробнее. Желательно с доказательными примерами.
Ega23 (2007-01-09 18:05:00) [50]
> [3] от региональных настроек не зависит никоем образом.
Невооружённым взглядом видно, что зависит.
02.03.04 кастоваться по-разному будет.
Ega23 (2007-01-09 18:03:00) [51]
> Охотно верю. Только причём он тут?
Ты [4] внимательно читал, или как?
Desdechado (2007-01-09 17:58:00) [52]try (09.01.07 17:49) [9]
Ты бы попробовал сначала, ага?
Не первый раз уже такую пургу несешь...
Desdechado (2007-01-09 17:54:00) [53]гораздо правильнее методически вот так
select cast( 'now' as TIMESTAMP ) -
extract( hour FROM cast( 'now' as timestamp ) )/24 -
extract( minute FROM cast( 'now' as timestamp ) )/24/60 -
extract( second FROM cast( 'now' as timestamp ) )/24/60/60
from rdb$database
try (2007-01-09 17:49:00) [54]
> Ega23 © (09.01.07 17:32) [7]
> В TSQL - как два байта переслать кастуются.
Охотно верю. Только причём он тут?
> Desdechado © (09.01.07 17:46) [8]
[3] от региональных настроек не зависит никоем образом.
Desdechado (2007-01-09 17:46:00) [55][3] и [6] слишком зависимо от региональных настроек сервера и может работать неправильно (разделители не те, порядок месяцев-дней не тот, наличие-отстутствие лидирующих нулей в номере дня/месяца, короткий-длинный год).
Ega23 (2007-01-09 17:32:00) [56]
> Даты и времена к численным типам не кастуются никаким образом.
>
>
В TSQL - как два байта переслать кастуются.
novill (2007-01-09 17:31:00) [57]сработало [3]
спасибо
Путем некоторых махинаций пришел к несколько более простому виду
datevalue=CAST(cast(datevalue as varchar(11)) as date)
try (2007-01-09 17:19:00) [58]
> Ega23 © (09.01.07 16:56) [4]
Даты и времена к численным типам не кастуются никаким образом.
Ega23 (2007-01-09 16:56:00) [59]Это на TSQL. Общая идея: Cast as int и опять cast as datetime
declare @dt datetime
Set @dt=getdate()
Select Cast(Cast(@dt as int) as datetime)
try (2007-01-09 16:54:00) [60]DateValue=CAST(EXTRACT(DAY FROM DateValue)||'.'||EXTRACT(MONTH FROM DateValue)||'.'||EXTRACT(YEAR FROM DateValue) AS DATE);