PostgreSQL에서 현재 유닉스 타임 스탬프를 어떻게 얻습니까?


91

유닉스 타임 스탬프 는 1970 년 1 월 1 일 UTC 자정 이후의 초 수입니다.

PostgreSQL에서 올바른 유닉스 타임 스탬프를 어떻게 얻습니까?

currenttimestamp.comtimestamp.1e5b.de 와 비교할 때 PostgreSQL에서 예상 시간을 얻지 못했습니다.

올바른 타임 스탬프를 반환합니다.

SELECT extract(epoch from now());

이것은 아니지만 :

SELECT extract(epoch from now() at time zone 'utc');

시간대 UTC +02에 살고 있습니다. PostgreSQL에서 현재 유닉스 타임 스탬프를 얻는 올바른 방법은 무엇입니까?

올바른 시간과 시간대를 반환합니다.

SELECT now();
              now
-------------------------------
 2011-05-18 10:34:10.820464+02

또 다른 비교 :

select now(), 
extract(epoch from now()), 
extract(epoch from now() at time zone 'utc');
              now              |    date_part     |    date_part
-------------------------------+------------------+------------------
 2011-05-18 10:38:16.439332+02 | 1305707896.43933 | 1305700696.43933
(1 row)

Unix timestamp from the web sites:
1305707967

답변:


82

postgres에서는 , 및 로 timestamp with time zone약칭 할 수 있습니다 . 간략화를 위해 더 짧은 유형 이름을 사용합니다.timestamptztimestamp without time zonetimestamp

포스트 그레스에서 유닉스 타임 스탬프를 얻기 timestamptz처럼 now()당신이 말한대로, 간단 단지 :

select extract(epoch from now());

timestamptz포함하여 모든 유형에서 절대 시간을 얻는 것에 대해 알아야 할 모든 것이 있습니다 now().

timestamp필드 가있을 때만 상황이 복잡해집니다 .

해당 필드 에 timestamptz데이터 를 넣으면 now()먼저 특정 시간대 at time zone로 변환되거나 ( 세션 시간대로 명시 적으로 또는 세션 시간대로 변환하여) 시간대 정보 가 삭제됩니다 . 더 이상 절대 시간을 의미하지 않습니다. 그렇기 때문에 일반적으로 타임 스탬프를 저장하고 싶지 않고 일반적 timestamp으로 사용하는 것이 좋습니다 timestamptz. 영화는 모든 시간대 의 특정 날짜 오후 6시에 출시 될 것입니다. 이것이 바로 유스 케이스입니다.

단일 시간대에서만 작업하는 경우을 사용하여 벗어날 수 있습니다 timestamp. timestamptzDST에 대응하기에 충분한 전환 은 영리하며 타임 스탬프는 변환을 위해 현재 시간대에있는 것으로 가정합니다. GMT / BST의 예는 다음과 같습니다.

select '2011-03-27 00:59:00.0+00'::timestamptz::timestamp::timestamptz
     , '2011-03-27 01:00:00.0+00'::timestamptz::timestamp::timestamptz;

/*
|timestamptz           |timestamptz           |
|:---------------------|:---------------------|
|2011-03-27 00:59:00+00|2011-03-27 02:00:00+01|
*/

DBFiddle

그러나 다음과 같은 혼란스러운 동작에 유의하십시오.

set timezone to 0;

values(1, '1970-01-01 00:00:00+00'::timestamp::timestamptz)
    , (2, '1970-01-01 00:00:00+02'::timestamp::timestamptz);

/*
|column1|column2               |
|------:|:---------------------|
|      1|1970-01-01 00:00:00+00|
|      2|1970-01-01 00:00:00+00|
*/

DBFiddle

이유는 다음과 같습니다.

PostgreSQL은 유형을 결정하기 전에 리터럴 문자열의 내용을 검사하지 않으므로 […]를 표준 시간대없이 타임 스탬프로 처리합니다. 리터럴이 시간대가있는 타임 스탬프로 처리되도록하려면 정확한 명시 적 유형을 지정하십시오… 시간대가없는 타임 스탬프로 결정된 리터럴에서 PostgreSQL은 모든 시간대 표시를 자동으로 무시합니다.


결과 소수를 소수점없이 정수로 변환하는 방법에 대한 아이디어 (숫자와 소수를 하나의 큰 정수로 병합하는 것을 의미합니다). 감사.
WM

마찬가지로 하지만 난 당신이 정말하고 싶지 않아 확신합니다. 아마도 10의 거듭 제곱을 곱하고 나머지 소수점을 제거하고 싶습니까?
잭 더글러스

2
@WM 어쩌면 이것처럼? SELECT FLOOR(EXTRACT(epoch FROM NOW())*1000);
Joe23

21
SELECT extract(epoch from now() at time zone 'utc');

postgres 시간대 변환이 결과에서 시간대 정보를 제거하기 때문에 올바른 타임 스탬프를 반환하지 않습니다.

9.9.3. 시간대에

구문 : 시간대가없는 타임 스탬프 AT TIME ZONE zone
반환 값 : 시간대가있는
타임 스탬프 지정된 시간대에있는 시간대가없는 지정된 타임 스탬프

구문 : 시간대가있는 타임 스탬프 AT TIME ZONE zone
반환 값 : 시간대가 없는 타임 스탬프 시간대가
지정된 지정된 타임 스탬프를 시간대가 지정되지 않은 새 시간대로 변환합니다.

그 후 extract는 시간대가없는 타임 스탬프를보고 현지 시간으로 간주합니다 (실제로는 utc 임).

올바른 방법은 다음과 같습니다.

select now(),
       extract(epoch from now()),                                          -- correct
       extract(epoch from now() at time zone 'utc'),                       -- incorrect
       extract(epoch from now() at time zone 'utc' at time zone 'utc');    -- correct

          now                  |    date_part     |    date_part     |    date_part
-------------------------------+------------------+------------------+------------------
 2014-10-14 10:19:23.726908+02 | 1413274763.72691 | 1413267563.72691 | 1413274763.72691
(1 row)

마지막 줄에서 첫 번째 at time zone변환을 수행하고 두 번째 줄에서 새 시간대를 결과에 할당합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.