2012-02-04 2 views
4

"날짜 + 시간"을 PostgreSQL 데이터베이스에 어떻게 저장해야합니까?시간대와 독립적으로 같은 날짜와 시간을 얻는 방법

이것은 내가 달성하고자하는 것입니다 :

  1. 어떻게 할 수 있습니다 세계 어디서나 1월 1일 (예를 들어) 2012 0시 0분 0초 현지 시간에 발생한 모든 항목?
  2. 모든 항목을 UTC 시간에 따라 날짜별로 정렬하여 표시합니다. (뉴욕의 2012 New Year Eve는 런던의 New Year보다 최근입니다.)

데이터를 어떻게 저장해야합니까? PostgreSQL 스토어를 내부적으로 UTC (PostgreSQL documentation)로 저장하므로 사용자 시간대가 실제로 손실됩니다.

은 내가 "시간대없이 타임 스탬프"유형의 하나 개의 컬럼을 사용한다고 생각 :

  • 포인트 1 쉽다.
  • 그리고 유형 "문자열"의 또 다른 열이
  • 나는 시간대 문자열을 저장합니다 (예 : 미국/뉴욕) 하지만, 점 2는 아직도 어려운 것 같습니다 ....

나는 내가 희망 명확한.

편집 새로운 아이디어 : 저는 두 타임 스탬프를 저장으로 생각 : 시간대 (1. OK)없이 하나의 시간대와 하나 (2 OK)

답변

1

예, PostgreSQL은 모든 타임 스탬프를 내부적으로 UTC로 저장합니다. timestamp with time zone의 경우 시간대 오프셋은 UTC로 시간을 조정하는 데에만 적용되지만 명시 적으로 저장되지는 ​​않습니다.

나는 시간대 문자열 또는 그 이하의 시간대 약어 (정확한 것은 아닙니다)를 저장하지 않을 것입니다. 이것은 일광 절약 시간 및 기타 국제 시간 체계의 기이함을 고려해야하기 때문에 나중에 값 비싼 계산이 필요할 수 있습니다.

넌 간격으로 오프셋 시간대를 저장할 수 중 어느 하나 또는 초 수치 량 (12 바이트 소요) I이 related answer에서 보여 같은 (정수 4 바이트 소요).

또는 이미 제안한 것처럼 : 로컬 타임 스탬프를 UTC 타임 스탬프와 함께 저장하십시오 (8 바이트 걸림). 그렇게하면 작업이 쉬워집니다.를 입력 할 수도 있습니다 솔루션

SELECT * 
FROM tbl 
ORDER BY ts_tz; 

id |   ts_tz   |   ts 
----+------------------------+--------------------- 
    4 | 2011-12-31 21:02:00+01 | 2012-01-01 00:02:00 
    3 | 2011-12-31 22:01:00+01 | 2012-01-01 00:01:00 
    2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00 
    1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00 

까다로운 부분 : 질문 2

SELECT * 
FROM tbl 
WHERE ts = '2012-1-1 00:00'::timestamp; 

id |   ts_tz   |   ts 
----+------------------------+--------------------- 
    1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00 
    2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00 

쿼리 : 다음 데모 : 질문 1

-- DROP TABLE tbl; 
CREATE TEMP TABLE tbl (id int, ts_tz timestamp with time zone, ts timestamp); 
INSERT INTO tbl VALUES 
(1,'2012-1-1 00:00+01','2012-1-1 00:00+01') 
,(2,'2012-1-1 00:00+02','2012-1-1 00:00+02') 
,(3,'2012-1-1 00:01+03','2012-1-1 00:01+03') 
,(4,'2012-1-1 00:02+04','2012-1-1 00:02+04'); 

쿼리를 고려 로컬 타임 스탬프. 모든 데이터가 로컬에 입력되는 한 쉽습니다. 그러나 로스 앤젤레스에 뉴욕에 대한 데이터를 입력하는 경우 고려해야합니다. 그에 대한 AT TIME ZONE construct를 사용하여 내가 입력으로 시간대와 타임 스탬프 을 사용하는 방법

SELECT ('2012-1-1 00:00+00' AT TIME ZONE 'America/New_York')::timestamp 
    , ('2012-1-1 00:00+00' AT TIME ZONE 'America/Los_Angeles')::timestamp 

     timezone  |  timezone 
---------------------+--------------------- 
2011-12-31 19:00:00 | 2011-12-31 16:00:00 

참고. AT TIME ZONE은 시간대가 있거나없는 시간 소인에 대해 다른 결과를 제공합니다.

0

난 당신이 문자열로 날짜를 저장하고 ISO 8601을 사용할 수있는 것 같아요 또는 RFC 2822에 따라 표준 시간대를 저장할 수도 있습니다. 또는 실제로 비교 옵션으로 타임 스탬프와 시간대를 두 개의 다른 열에 저장하십시오.

+0

날짜/시간을 문자열로 저장하는 것은 매우 더러운 일이므로 피해야합니다. – Skuld

+0

데이터베이스의 날짜/시간 필드가 항상 문자열이 아닙니까? 그리고 나는 쿼리에서 비교할 수 있지만 ISO 8601 문자열로 저장하지 않아도된다고 동의한다. –

+0

postgresql이 다른 데이터베이스 엔진과 다른 점이 없으면 datetime은 문자열로 저장되지 않는다. 과거의 특정 날짜/시간에서 정의 된 시간을 나타내는 정수 값) – Skuld

관련 문제