데이터 유형이 WITH TIME ZONE
vs 일 때 타임 스탬프 값이 PostgreSQL에 다르게 저장 WITHOUT TIME ZONE
됩니까? 간단한 테스트 사례로 차이점을 설명 할 수 있습니까?
답변
차이점은 날짜 / 시간 유형에 대한 PostgreSQL 설명서 에서 다룹니다 . 예, 치료 TIME
또는 TIMESTAMP
하나를 사이에 다릅니다 WITH TIME ZONE
나 WITHOUT TIME ZONE
. 값이 저장되는 방식에는 영향을 미치지 않습니다. 해석 방법에 영향을줍니다.
이러한 데이터 형식에 대한 표준 시간대의 영향은 문서에서 구체적 으로 다룹니다 . 차이점은 시스템이 가치에 대해 합리적으로 알 수있는 것과 다릅니다.
-
시간대를 값의 일부로 사용하면 값을 클라이언트에서 현지 시간으로 렌더링 할 수 있습니다.
-
값의 일부로 시간대가 없으면 명백한 기본 시간대는 UTC이므로 해당 시간대에 대해 렌더링됩니다.
동작은 최소한 세 가지 요소에 따라 다릅니다.
- 클라이언트의 시간대 설정
- 값의 데이터 유형 (예 :
WITH TIME ZONE
또는WITHOUT TIME ZONE
) - 값이 특정 시간대로 지정되었는지 여부
이러한 요소의 조합을 다루는 예는 다음과 같습니다.
foo=> SET TIMEZONE TO 'Japan';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+09
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 06:00:00+09
(1 row)
foo=> SET TIMEZONE TO 'Australia/Melbourne';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+11
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 08:00:00+11
(1 row)
답변
참조 된 PostgreSQL 설명서보다 이해하기 쉽게 설명하려고합니다.
TIMESTAMP
변형은 이름에서 제안하는 내용에도 불구하고 시간대 (또는 오프셋)를 저장 하지 않습니다 . 차이점은 저장 형식 자체가 아니라 저장된 데이터 (및 의도 된 응용 프로그램)의 해석에 있습니다.
-
TIMESTAMP WITHOUT TIME ZONE
저장 현지 날짜 – 시간 (일명. 벽에 달력의 날짜와 벽 시계 시간). 표준 시간대는 PostgreSQL이 알 수있는 한 미지정입니다 (응용 프로그램이 무엇인지 알 수 있음). 따라서 PostgreSQL은 입력 또는 출력에서 표준 시간대 관련 변환을 수행하지 않습니다. 값을로 데이터베이스에 입력'2011-07-01 06:30:30'
한 후 나중에 표시 할 시간대에 상관이없는 경우에도 2011 년, 월 07, 일 01, 06 시간, 30 분 및 30 초 (일부 형식)로 표시됩니다. 또한, 모든 오프셋 또는 입력에 지정한 시간대는 PostgreSQL을 무시하므로'2011-07-01 06:30:30+00'
와'2011-07-01 06:30:30+05'
마찬가지로 동일합니다'2011-07-01 06:30:30'
. Java 개발자의 경우 :와 유사합니다java.time.LocalDateTime
. -
TIMESTAMP WITH TIME ZONE
UTC 타임 라인에 포인트를 저장합니다. 어떻게 보이는지 (시간, 분 등)는 시간대에 따라 다르지만 항상 실제 “실제 사건의 순간”과 같은 “물리적”순간을 나타냅니다. 입력은 내부적으로 UTC로 변환되어 저장되는 방식입니다. 이를 위해서는 입력의 오프셋을 알고 있어야합니다. 따라서 입력에 명시적인 오프셋이나 시간대 (예 :)가 포함되어 있지'2011-07-01 06:30:30'
않으면 PostgreSQL 세션의 현재 시간대에있는 것으로 간주됩니다. 그렇지 않으면 명시 적으로 지정된 오프셋 또는 시간대가 사용됩니다 (에서와 같이'2011-07-01 06:30:30+05'
). 출력은 PostgreSQL 세션의 현재 시간대로 변환되어 표시됩니다. Java 개발자의 경우 :java.time.Instant
해상도는 낮지 만 JDBC 및 JPA 2.2에서는이를 매핑해야합니다java.time.OffsetDateTime
(java.util.Date
또는java.sql.Timestamp
물론이야).
어떤 사람들은 두 TIMESTAMP
변형이 UTC 날짜-시간을 저장 한다고 말합니다 . 내 생각에는 그렇게하는 것이 혼란 스럽습니다. TIMESTAMP WITHOUT TIME ZONE
은 TIMESTAMP WITH TIME ZONE
UTC 시간대로 렌더링되어 현지 날짜-시간과 동일한 연도, 월, 일,시, 분, 초 및 마이크로 초를 제공하는으로 저장됩니다. 그러나 UTC 해석에서 말하는 타임 라인의 요점을 나타내는 것은 아니며 현지 날짜-시간 필드가 인코딩되는 방식입니다. (실시간 시간대는 UTC가 아니기 때문에 타임 라인의 일부 점입니다. 우리는 그것이 무엇인지 알 수 없습니다.)
답변
여기 도움이 될만한 예가 있습니다. 시간대가있는 타임 스탬프가있는 경우 해당 타임 스탬프를 다른 시간대로 변환 할 수 있습니다. 기본 시간대가 없으면 올바르게 변환되지 않습니다.
SELECT now(),
now()::timestamp,
now() AT TIME ZONE 'CST',
now()::timestamp AT TIME ZONE 'CST'
산출:
-[ RECORD 1 ]---------------------------
now | 2018-09-15 17:01:36.399357+03
now | 2018-09-15 17:01:36.399357
timezone | 2018-09-15 08:01:36.399357
timezone | 2018-09-16 02:01:36.399357+03