답변:
차이점은 날짜 / 시간 유형에 대한 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)
timestamp with time zone
과 실제로 시간대 정보를 저장 하지 않는다는 것을 이해해야합니다 . 데이터 유형 문서 페이지에서이를 한눈에 확인할 수 있습니다. 두 유형 모두 같은 수의 옥텟을 차지하고 저장 범위의 값을 가지므로 시간대 정보를 저장할 공간이 없습니다. 페이지의 텍스트가이를 확인합니다. 잘못된 의미 : "tz없이"는 "데이터 삽입시 오프셋 무시"를 의미하고 "tz로"는 "UTC로 조정하기 위해 오프셋 사용"을 의미합니다. timestamp without time zone
참조 된 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가 아니기 때문에 타임 라인의 일부 점입니다. 우리는 그것이 무엇인지 알 수 없습니다.)
TIMESTAMP WITH TIME ZONE
로 검색해도 아무런 문제가 없습니다 Instant
. 둘 다 타임 라인의 한 지점을 UTC로 나타냅니다. Instant
내 의견 OffsetDateTime
으로는 더 많은 자체 문서화 가 선호 됩니다 .A TIMESTAMP WITH TIME ZONE
는 항상 데이터베이스에서 UTC로 검색되고 A 는 항상 Instant
UTC이므로 자연스럽게 일치하지만 OffsetDateTime
다른 오프셋을 가질 수 있습니다.
OffsetDateTime
는 매핑 된 Java 유형으로 만 언급 됩니다. Instance
어딘가에서 비공식적으로 지원 되는지 확실하지 않습니다 .
'2011-07-01 06:30:30+00'
하고 '2011-07-01 06:30:30+05'
무시하지만 할 수 insert into test_table (date) values ('2018-03-24T00:00:00-05:00'::timestamptz);
있으며 올바르게 utc로 변환합니다. 여기서 날짜는 시간대가없는 타임 스탬프입니다. 시간대가있는 타임 스탬프의 주요 가치가 무엇인지 이해하고 노력하고 있습니다.
::timestamptz
. 당신의 문자열을 변환하는 것이로 TIMESTAMP WITH TIME ZONE
, 그리고 추가로 변환 될 때 WITHOUT TIME ZONE
, 즉 (어쩌면 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
timestamp
을 timestamptz
의미 하는지 이해해야합니다 . timestamptz
"절대 시간 (UTC)" timestamp
은 시계가 특정 시간대에서 보여준 것을 나타냅니다. 따라서 timestamptz
시간대 로 변환 할 때이 절대 시점에서 시계가 뉴욕에서 무엇을 보여 주었습니까? 반면에 "변환" 할 때 뉴욕의 시계가 x를 표시했을 때 절대 시점이 무엇인지timestamp
묻고 있습니까?
AT TIME ZONE
이미 이해하더라도 구조는, 자신의 티저 뇌입니다 WITH
대의 WITHOUT TIME ZONE
유형. 그것들을 설명하는 것은 호기심 많은 선택입니다. (: ( 타임 스탬프를 타임 스탬프 AT TIME ZONE
로 변환 하고 그 반대도 마찬가지입니다. 정확히 알 수 없습니다.)WITH TIME ZONE
WITHOUT TIME ZONE
now()::timestamp AT TIME ZONE 'CST'
'CST'구역의 시계가 현지 시계가 현재 표시되는 시간을 어떤 순간에 표시 할 것인지를 제외하고는 의미가 없습니다.