Гость
Map
Форумы / Informix [игнор отключен] [закрыт для гостей] / Как преобразовать DATETIME в UTC? / 11 сообщений из 11, страница 1 из 1
30.12.2009, 15:59
    #36394115
victor16
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
Есть функция dbinfo("utc_to_datetime"), а вот обратное преобразование выполнить не удается.
Может кто решал аналогичную проблему, или, хотя бы, как узнать количество секунд между двумя DATETIME?

С уважением,
Виктор
...
Рейтинг: 0 / 0
30.12.2009, 19:06
    #36394504
vasilis
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
victor16Есть функция dbinfo("utc_to_datetime"), а вот обратное преобразование выполнить не удается.
DBA_Tools\SQL\proc\sp_datetime2utc.sql
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
------------------------------------------------------------
-- Converting a datetime (year to second) value to UTC format 
--  Larry Kemmerling, CDI 2006-04
--
--   (Look at %DBA%\sql\proc\sp_dt2utc.sql for second example)
------------------------------------------------------------
CREATE PROCEDURE datetime2utc
      ( Datetime_in    datetime year to second )
        RETURNING      integer;
        DEFINE offSet  interval second( 9 ) to second;
        DEFINE UTC    interval second( 9 ) to second;
        DEFINE UTCC    char( 10 );
        DEFINE UTCI    integer;
        DEFINE epoch  datetime year to second;
-- set debug file to '/tmp/datetime2utc_trace';         
-- trace on;
-- When UTC time begins
        LET epoch = DATETIME(  1970 - 01 - 01   00 : 00 : 00  ) YEAR TO SECOND;   
-- Compute an offset that accounts for TZ
        LET offSet = ( SELECT CURRENT - ( epoch + DBINFO('utc_current') UNITS SECOND )                           
                       FROM SysTables WHERE TabId =  99  );
-- Compute the 'interval' value
        LET UTC = ( Datetime_in - epoch - offSet );
-- Convert the interval to char
        LET UTCC = UTC;
-- Convert the char to integer
        LET UTCI = UTCC;
-- NOTE: Discrepancies of 1-2 seconds may occur on busy systems.         
        RETURN UTCI;
END PROCEDURE;

{I haven't done any exhaustive testing but this procedure seems to
 produce correct results on my test system (Solaris 2.6, IDS 7.31.UC2).
 Also note that I intend to use this in situations where the datetime
 value passed in is not more than a few hours off of the current time.
 One problem I'm seeing is discrepancies of  1 - 2  seconds can occur on
 busy systems.

 I was hoping there was a dbinfo function to handle this but I haven't
 been able to find one.  Does such a function exist?  Is there a better
 way to do this?
}
\DBA_Tools\SQL\proc\sp_dt2utc.sql
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
---------------------------------------------------------
-- Convert DateTime to UnixTimeClock (UTC) (time_t)
-- Jonathan Leffler, CDI  2000-05
--    (Look at %DBA%\sql\proc\sp_datetime2utc.sql)
---------------------------------------------------------
-- dbinfo('UTC_TO_DATETIME',connected) to convert the
-- value in sysmaster:syssessions.connected to a datetime value 

CREATE PROCEDURE dt2utc(dt DATETIME YEAR TO SECOND) 
      RETURING INT;
    DEFINE i INTERVAL SECOND( 9 ) TO SECOND;
    DEFINE s CHAR( 10 );
    LET i = dt - DATETIME( 1970 - 01 - 01   00 : 00 : 00 ) YEAR TO SECOND;
    LET s = i;
    RETURN s;
END PROCEDURE;

--Yes, you do have to use a string in there.  The problem is that in
--2001 sometime, the Unix clock moves from 9 digits to 10 digits, and
--10 digits won't fit into an INTERVAL SECOND(9) TO SECOND variable.
--At that point, you have to do the reduction in two stages:
--1. Deal in whole days and multiple by 86400 (24*60*60).
--2. Deal in the hour to second part.
--More fiddly than difficult, but necessary for dates more than 30-odd
--years either side of 1970.
...
Рейтинг: 0 / 0
30.12.2009, 19:57
    #36394553
victor16
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
Василий, я уже пробовал эти процедуры. К сожалению, в 11.50 они неработоспособны.
Первая приводит к ошибке -1266: Intervals or datetimes are incompatible for the operation.
Вторая также -1265: Overflow occurred on a datetime or interval operation.
Если бы у меня отрабатывался запрос
Код: plaintext
1.
2.
SELECT CAST(CURRENT YEAR TO SECOND - DATETIME( 1970 - 01 - 01   00 : 00 : 00 ) YEAR TO SECOND AS INTERVAL SECOND( 9 ) TO SECOND)
FROM sysmaster:sysdual
вопросов бы не было.
...
Рейтинг: 0 / 0
30.12.2009, 20:25
    #36394590
victor16
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
Кстати, в комментариях ко второй процедуре есть ответ на мой вопрос.
Дело в том, количество секунд с 1 января 1970 года уже стало десятизначным числом, начиная с 2001 года.
А максимальное количество цифр в типе данных INTERVAL равно 9.
Видимо, придется обратиться в support.

С уважением,
Виктор
...
Рейтинг: 0 / 0
30.12.2009, 21:35
    #36394626
vasilis
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
victor16Кстати, в комментариях ко второй процедуре есть ответ на мой вопрос.
ну так там же предлагается и некий вариант решения ?
--At that point, you have to do the reduction in two stages:
--1. Deal in whole days and multiple by 86400 (24*60*60).
--2. Deal in the hour to second part.
...
Рейтинг: 0 / 0
30.12.2009, 21:41
    #36394633
vasilis
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
Кстати, может подскажет вариант из DBA_Tools\DOC\FAQ_IDS_Time_processing.txt

Код: plaintext
1.
2.
3.
4.
5.
-- После 2001-09-09 01:46:39 (by Alex Gradinar)
        ,CASE WHEN sh_curtime >  999999999 
         THEN DATETIME( 1970 - 01 - 01   00 : 00 : 00 ) YEAR TO SECOND +  999999999  UNITS SECOND +
                (sh_curtime -  999999999 ) UNITS SECOND
         ELSE DATETIME(  1970 - 01 - 01   00 : 00 : 00  ) YEAR TO SECOND + sh_curtime UNITS SECOND
         END AS                         GMT_sysshmvals
...
Рейтинг: 0 / 0
30.12.2009, 22:01
    #36394645
victor16
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
В DBA_Tools\DOC\FAQ_IDS_Time_processing.txt решается обратная задача,
мне же нужно преобразовать DATETIME в UTC.
...
Рейтинг: 0 / 0
31.12.2009, 09:42
    #36394885
victor16
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
Вот, наваял собственный вариант, с учетом 9 сентября 2001 года.
Работает с датами от 1970-01-01 00:00:01 до 2033-05-18 03:33:18,
иначе возвращает NULL.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
-- DROP PROCEDURE dt2utc(DATETIME YEAR TO SECOND);
CREATE PROCEDURE dt2utc(dt DATETIME YEAR TO SECOND) RETURNING INTEGER;
 DEFINE utcd_begin DATETIME YEAR TO SECOND;
 DEFINE fatal_time DATETIME YEAR TO SECOND;
 DEFINE fatal_time2 DATETIME YEAR TO SECOND;
 DEFINE fatal_int INTEGER;
 DEFINE gmt_offset INTEGER;
 DEFINE gmt DATETIME YEAR TO SECOND;
 DEFINE current_time DATETIME YEAR TO SECOND;
 DEFINE utci_current INTEGER;
 DEFINE utci INTEGER;
 DEFINE utc_val INTERVAL SECOND( 9 ) TO SECOND;
 
 LET utcd_begin = DATETIME( 1970 - 01 - 01   00 : 00 : 00 ) YEAR TO SECOND;
 LET fatal_time = DATETIME( 2001 - 09 - 09   01 : 46 : 39 ) YEAR TO SECOND;
 LET fatal_time2 = DATETIME( 2033 - 05 - 18   03 : 33 : 18 ) YEAR TO SECOND;
 LET fatal_int =  999999999 ;
 LET utci_current = dbinfo("utc_current");
 LET current_time = CURRENT YEAR TO SECOND;

 IF utci_current > fatal_int
 THEN LET gmt = utcd_begin + (fatal_int UNITS SECOND) + ((utci_current - fatal_int) UNITS SECOND);
 ELSE LET gmt = utcd_begin + (utci_current UNITS SECOND);
 END IF;
 LET gmt_offset = CAST(CAST(CAST(current_time - gmt AS INTERVAL SECOND( 9 ) TO SECOND) AS CHAR( 20 )) AS INTEGER);

 IF dt > utcd_begin AND dt <= fatal_time
 THEN
   LET utc_val = CAST((dt - utcd_begin) AS INTERVAL SECOND( 9 ) TO SECOND);
   LET utci = CAST(CAST(utc_val AS CHAR( 20 )) AS INTEGER);
 ELIF dt > fatal_time AND dt <= fatal_time2 THEN
   LET utc_val = CAST((dt - fatal_time) AS INTERVAL SECOND( 9 ) TO SECOND);
   LET utci = CAST(CAST(utc_val AS CHAR( 20 )) AS INTEGER) + fatal_int;
 ELSE RETURN NULL;
 END IF;
 LET utci = utci - gmt_offset;

 RETURN utci;

END PROCEDURE;

-- DROP TABLE tmptb;
CREATE TEMP TABLE tmptb(dt DATETIME YEAR TO SECOND);
INSERT INTO tmptb VALUES (DATETIME( 1970 - 01 - 01   00 : 00 : 01 ) YEAR TO SECOND);
INSERT INTO tmptb VALUES (DATETIME( 2001 - 09 - 09   01 : 46 : 39 ) YEAR TO SECOND);
INSERT INTO tmptb VALUES (CURRENT YEAR TO SECOND);

SELECT dt,dt2utc(dt) FROM tmptb;


С уважением,
Виктор
...
Рейтинг: 0 / 0
31.12.2009, 13:45
    #36395129
vasilis
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
Вот нашел в своих "закромах SQL.RU" еще один вариант, достаточно компактный.
Проверь - может он и подойдет, а то у тебя как то сложно :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
---------------------------------------------------------
-- zest (SQL.RU 2005-04) 
---------------------------------------------------------
DROP FUNCTION Datetime2Second;
CREATE FUNCTION Datetime2Second (dt DATETIME YEAR TO SECOND)
        RETURNING INT;
        DEFINE checkpoint INT;
        DEFINE curr INTERVAL SECOND( 9 ) TO FRACTION; 
        DEFINE retval INT;
        LET checkpoint =  946684800 ;             
        LET curr = dt - EXTEND(DATE('1/1/2000'), YEAR TO FRACTION); 
        LET retval = CAST(CAST(curr AS VARCHAR( 64 )) AS INT);
        RETURN (retval +  946684800 ) ;
END FUNCTION;
...
Рейтинг: 0 / 0
08.01.2010, 22:07
    #36401081
victor16
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
Василий, этот вариант тоже неудачен. Опять ошибка -1265: Overflow occurred on a datetime or interval operation.

С уважением,
Виктор
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
03.08.2016, 11:41
    #39285200
victor16
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как преобразовать DATETIME в UTC?
vasilisа то у тебя как то сложно :)

Действительно, сложновато получилось. Наконец, нашел рабочий вариант попроще:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
CREATE PROCEDURE dt2utc(d DATETIME YEAR TO FRACTION(5))
            RETURNING INTEGER;
    DEFINE n INTEGER;
    DEFINE i1 INTERVAL DAY(9) TO DAY;
    DEFINE i2 INTERVAL SECOND(6) TO FRACTION(5);
    DEFINE s1 CHAR(15);
    DEFINE s2 CHAR(15);
    LET i1 = EXTEND(d, YEAR TO DAY) - DATETIME(1970-01-01) YEAR TO DAY;
    LET s1 = i1;
    LET i2 = EXTEND(d, HOUR TO FRACTION(5)) -
                DATETIME(00:00:00.00000) HOUR TO FRACTION(5);
    LET s2 = i2;
    LET n = s1 * (24 * 60 * 60) + s2;
    RETURN n;
END PROCEDURE;
...
Рейтинг: 0 / 0
Форумы / Informix [игнор отключен] [закрыт для гостей] / Как преобразовать DATETIME в UTC? / 11 сообщений из 11, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]