суббота, 27 ноября 2010 г.

Get a difference between dates (получить разницу между датами)

Распространенный вопрос, при вычитании получается число, и что с ним делать дальше часто никто не знает, либо начинают сочинять невероятные решения.

После появления в Oracle интервальных типов:
  • INTERVAL YEAR TO MONTH
  • INTERVAL DAY TO SECOND
жить стало проще и разницу дат можно представить в виде интервала INTERVAL DAY TO SECOND (в днях/часах/минутах/секундах/милисекундах), используя следующие функции:

Формат NUMTODSINTERVAL(n, 'interval_unit'):
  • NUMTODSINTERVAL(5, 'DAY')
  • NUMTODSINTERVAL(21, 'HOUR')
  • NUMTODSINTERVAL(10, 'MINUTE')
  • NUMTODSINTERVAL(15, 'SECOND')

Формат TO_DSINTERVAL('D HH:MI:SS'):
  • TO_DSINTERVAL('5 21:10:15')

Примеры:

alter session set nls_date_format = 'DD.MM.YYYY HH24:MI:SS';

COLUMN DSINTERVAL2 FORMAT A20
COLUMN DSINTERVAL3 FORMAT A20

with dates as (
  select to_date('20.11.2010 23:10:05', 'DD.MM.YYYY HH24:MI:SS') date_begin,
         to_date('26.11.2010 20:20:20', 'DD.MM.YYYY HH24:MI:SS') date_end
    from dual
)
select d.*,
       --Разница дат в до появления интервальных типов
       date_end - date_begin date_diffirence,
       --Приведение к интервальному типу при помощи NUMTODSINTERVAL
       NUMTODSINTERVAL(date_end - date_begin, 'DAY') DSINTERVAL2,
       --Приведение к интервальному типу при помощи day(5) to second(0)
       (date_end - date_begin) day(5) to second(0) DSINTERVAL3,
       --Вычитаем из даты интервал
       date_end - TO_DSINTERVAL('5 21:10:15') DATE_BEGIN2,
       --Прибавляем к дате интервал
       date_begin + TO_DSINTERVAL('5 21:10:15') DATE_END2
  from dates d
 where 1 = 1
   and ( 
         numtodsinterval(date_end - date_begin, 'DAY') between numtodsinterval(-10, 'DAY') and numtodsinterval(10, 'DAY')
         or
         (date_end - date_begin) day(5) to second(0) between numtodsinterval(-10, 'DAY') and numtodsinterval(10, 'DAY')
         or
         (date_end - date_begin) day(5) to second(0) between to_dsinterval('-10 00:00:00') and to_dsinterval('10 00:00:00')
       )
;

DATE_BEGIN            DATE_END              DATE_DIFFIRENCE DSINTERVAL2         
--------------------- --------------------- --------------- --------------------
DSINTERVAL3          DATE_BEGIN2           DATE_END2            
-------------------- --------------------- ---------------------
20.11.2010 23:10:05   26.11.2010 20:20:20        5.88211806 +05 21:10:15.000000 
+05 21:10:15.000000  20.11.2010 23:10:05   26.11.2010 20:20:20  
                                                                                
1 row selected.

Комментариев нет:

Отправить комментарий