Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

IB 7.5 Как хр. процедуре в переменнной типа date обнулить время?


Страницы:   1 2 3 4

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);


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо