2016-11-16 2 views
1

READDATETIME이라는 오라클 테이블을 가지고 있는데 유닉스 타임 스탬프를 밀리 초 단위로 INTEGER (NUMBER(38)) 타입으로 저장합니다.ISO-8601 유닉스 타임 스탬프 문자열

SQL> select READDATETIME from ACQDATA where ID=1000; 

READDATETIME 
____________ 
    1.4793E+12 

가 나는 ISO-8601 문자열로 그 값 (YYYY-MM-DDTHH:MM:SS.mmm)을 선택해야합니다

SQL> select READDATETIME from ACQDATA where ID=1000; 

READDATETIME 
------------------- 
    1.4793E+12 

I've가 TO_CHAR를 사용하여 변환을 시도,하지만 결과는 지저분 :

SQL> select TO_CHAR(TO_DATE('1970-01-01','YYYY-MM-DD') + NUMTODSINTERVAL(READDATETIME, 'SECOND'), 'YYYY-MM-DD HH24:MI:SS') from ACQDATA where ID=1000; 

Error at line 1: 
ORA-01873: the leading precision of the interval is too small  

감사합니다.

+1

을 년은 RO이다 힘들게 3 * 10^7 초. 'readDateTime'이 1970 년 1 월 1 일 이후의 초 수라면, 그것은 1970 년이나 10 만년 후에 대략 10 ~ 5 년이 될 것입니다. 그럴 것 같지 않습니다. 'readDateTime'이 밀리 세컨드 수라면 1970 년 이후 46 년이되는 날짜이므로 2016 년이 될 것입니다. –

+0

그래서'readdatetime'은 몇 초입니까? 그렇다면,'to_date (...) + readdatetime/86400' (첫 번째 용어는 1970 년 1 월 1 일) 저스틴 용의자가 밀리 초이면 86400000으로 나눕니다.그런 다음 필요에 따라 char로 변환 할 수 있습니다 (대부분의 경우 그렇게해서는 안됩니다). – mathguy

+0

readdatetime은 1970 년 1 월 1 일 이후의 밀리 초 단위 유닉스 타임 스탬프입니다. 원래 게시물에서 수정되었습니다. – Mendes

답변

2

Alex의 답변이 완전히 올바르지 않습니다. 세션이 정확한 솔루션은 다음과 같이 될 것이다 UTC 시간대에서 실행하지 않는 한 유닉스 타임 스탬프는 항상 1970-01-01 0시 0분 0초 UTC

을 기반으로합니다

select 
    TO_CHAR((TIMESTAMP '1970-01-01 00:00:00 UTC' + readdatetime/1000 * INTERVAL '1' SECOND) AT LOCAL, 'YYYY-MM-DD"T"HH24:MI:SS.FF3') 
from ACQDATA where ID=1000; 

또는

select 
    TO_CHAR((TIMESTAMP '1970-01-01 00:00:00' AT TIME ZONE 'UTC' + readdatetime/1000 * INTERVAL '1' SECOND) AT LOCAL, 'YYYY-MM-DD"T"HH24:MI:SS.FF3') 
from ACQDATA where ID=1000; 

이 기능을 대신 리터럴 선호하는 경우 나 :

select 
    TO_CHAR((TO_TIMESTAMP_TZ('1970-01-01 00:00:00 UTC', 'YYYY-MM-DD HH24:MI:SS TZR') + numtodsinterval(readdatetime/1000, 'SECOND')) AT LOCAL, 'YYYY-MM-DD"T"HH24:MI:SS.FF3') 
from ACQDATA where ID=1000; 
+0

감사합니다. 더 나은 지금. – Mendes

1

readdatetime은 밀리 초 단위 인 것 같습니다. 오라클 날짜 산술은 일 단위로 작동하므로, 해당 숫자를 나타내는 일 수로 변환해야합니다. 일일 86400 초입니다, 그래서 86,400,000 밀리 초입니다 :

with acqdata (id, readdatetime) as (
    select 1000, 1479318995000 from dual 
) 
select to_char(date '1970-01-01' + (READDATETIME/86400000), 'YYYY-MM-DD"T"HH24:MI:SS') 
from ACQDATA where ID=1000; 

TO_CHAR(DATE'1970-0 
------------------- 
2016-11-16T17:56:35 

Ta character literal으로 추가됩니다.

SQL Developer는 기본적으로 과학 표기법이 큰 숫자를 표시합니다. 당신의 값이 소수점 이하의 초를 가지고, 그래서 마지막 세 자리가 제로가 아닌 경우

select readdatetime, to_char(readdatetime, '9999999999999') as string 
from ACQDATA where ID=1000; 

READDATETIME STRING   
------------ -------------- 
    1.4793E+12 1479318995000 

, 당신은 타임 스탬프로 날짜를 변환하고 추가 할 수 있습니다 : 당신은 set numformat와 그 기본값을 변경하거나 전체 값을 보여 to_char()을 사용할 수 있습니다 부분 나머지에; @Wernfried 밖으로 ponted으로

with acqdata (id, readdatetime) as (
    select 1000, 1479300462063 from dual 
) 
select to_char(timestamp '1970-01-01 00:00:00' 
    + numtodsinterval(readdatetime/1000, 'SECOND'), 
    'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"') 
from acqdata where id=1000; 

TO_CHAR(TIMESTAMP'1970-0 
------------------------ 
2016-11-16T12:47:42.063Z 

, 명시 적으로 표시하는 것이 좋습니다 :

with acqdata (id, readdatetime) as (
    select 1000, 1479300462063 from dual 
) 
select to_char(cast(date '1970-01-01' + (readdatetime/86400000) as timestamp) 
    + numtodsinterval(remainder(readdatetime, 1000)/1000, 'SECOND'), 
    'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"') 
from acqdata where id=1000; 

TO_CHAR(CAST(DATE'1970-01-01'+ 
------------------------------ 
2016-11-16T12:47:42.063Z 

또는 중간 date 값없이

은, 문자 그대로의 타임 스탬프 시작 :이 또한 재미를 위해 UTC 'Z'표시를 추가 신기원 시간이 UTC에서 시작하는 것입니다 :

alter session set time_zone='America/New_York'; 

with acqdata (readdatetime) as (
    select 1479300462063 from dual 
    union all select 1467331200000 from dual 
    union all select 1467648000000 from dual 
) 
select readdatetime, 
    to_char(timestamp '1970-01-01 00:00:00' + numtodsinterval(readdatetime/1000, 'SECOND'), 
    'YYYY-MM-DD"T"HH24:MI:SS.FF3') as implicit, 
    to_char(cast(timestamp '1970-01-01 00:00:00' as timestamp with time zone) 
    + numtodsinterval(readdatetime/1000, 'SECOND'), 
    'YYYY-MM-DD"T"HH24:MI:SS.FF3TZH:TZM') as local_offset, 
    to_char(timestamp '1970-01-01 00:00:00 UTC' + numtodsinterval(readdatetime/1000, 'SECOND'), 
    'YYYY-MM-DD"T"HH24:MI:SS.FF3TZH:TZM') as utc_offset, 
    to_char(timestamp '1970-01-01 00:00:00 UTC' + numtodsinterval(readdatetime/1000, 'SECOND'), 
    'YYYY-MM-DD"T"HH24:MI:SS.FF3TZR') as utc 
from acqdata; 

    READDATETIME IMPLICIT    LOCAL_OFFSET     UTC_OFFSET     UTC      
-------------- ----------------------- ----------------------------- ----------------------------- -------------------------- 
1479300462063 2016-11-16T12:47:42.063 2016-11-16T12:47:42.063-05:00 2016-11-16T12:47:42.063+00:00 2016-11-16T12:47:42.063UTC 
1467331200000 2016-07-01T00:00:00.000 2016-07-01T01:00:00.000-04:00 2016-07-01T00:00:00.000+00:00 2016-07-01T00:00:00.000UTC 
1467648000000 2016-07-04T16:00:00.000 2016-07-04T17:00:00.000-04:00 2016-07-04T16:00:00.000+00:00 2016-07-04T16:00:00.000UTC 
+0

거의 다 왔어. 결과 문자열에서 밀리 초와'T'는 어디에 있습니까? ISO-8601은'YYYY-MM-DDTHH : MM : SS.mmm'을 정의합니다. 결과 문자열에는 T가없는 초만 포함됩니다. – Mendes

+0

T를 추가했습니다. 값에 실제로 밀리 초 값이 있습니까? 아니면 항상 000의 마지막 세 자리입니까? –

+0

특정 밀리 초 값을가집니다. 예제 값은 '1479300462063' (063 밀리 초)입니다. – Mendes

관련 문제