PostgreSQL에서 시간대가 있거나없는 타임 스탬프의 차이점


답변:


157

차이점은 날짜 / 시간 유형에 대한 PostgreSQL 설명서 에서 다룹니다 . 예, 치료 TIME또는 TIMESTAMP하나를 사이에 다릅니다 WITH TIME ZONEWITHOUT 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)

88
값 삽입 / 검색 프로세스를 참조하는 경우에만 수정하십시오. 그러나 독자는 Postgres의 두 데이터 유형 timestamp with time zone과 실제로 시간대 정보를 저장 하지 않는다는 것을 이해해야합니다 . 데이터 유형 문서 페이지에서이를 한눈에 확인할 수 있습니다. 두 유형 모두 같은 수의 옥텟을 차지하고 저장 범위의 값을 가지므로 시간대 정보를 저장할 공간이 없습니다. 페이지의 텍스트가이를 확인합니다. 잘못된 의미 : "tz없이"는 "데이터 삽입시 오프셋 무시"를 의미하고 "tz로"는 "UTC로 조정하기 위해 오프셋 사용"을 의미합니다. timestamp without time zone
Basil Bourque

42
데이터 유형은 두 번째 방법으로 잘못되었습니다. "시간대"라고 말하지만 실제로 UTC / GMT와의 오프셋에 대해 이야기하고 있습니다. 시간대는 실제로 일광 절약 시간제 (DST) 및 기타 예외에 대한 오프셋 규칙 / 역사입니다.
Basil Bourque

4
차라리 오프셋은 표준 시간대에 DST 규칙을 더한 것입니다. 오프셋이 지정된 시간대를 감지 할 수 없지만 시간대 및 DST 규칙이 지정된 오프셋을 감지 할 수 있습니다.
igorsantos07

3
공식 문서 인용 : 모든 시간대 인식 날짜 및 시간은 내부적으로 UTC로 저장됩니다. 클라이언트에 표시되기 전에 TimeZone 구성 매개 변수로 지정된 영역에서 현지 시간으로 변환됩니다.
기 illa Husta

2
@ igorsantos07 시간대 DST 변경 및 기타 변경에 대한 규칙 / 이력 세트입니다. 당신의 말은 불필요한 것 같습니다. "오프셋은 표준 시간대에 DST 규칙을 더한 것"이라는 진술은 단순히 잘못된 것입니다. 오프셋은 단지 몇 시간, 분, 초에 불과합니다.
Basil Bourque

34

참조 된 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 ZONEUTC 타임 라인에 포인트를 저장합니다. 어떻게 보이는지 (시간, 분 등)는 시간대에 따라 다르지만 항상 실제 "실제 사건의 순간"과 같은 "물리적"순간을 나타냅니다. 입력은 내부적으로 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 ZONETIMESTAMP WITH TIME ZONEUTC 시간대로 렌더링되어 현지 날짜-시간과 동일한 연도, 월, 일,시, 분, 초 및 마이크로 초를 제공하는으로 저장됩니다. 그러나 UTC 해석에서 말하는 타임 라인의 요점을 나타내는 것은 아니며 현지 날짜-시간 필드가 인코딩되는 방식입니다. (실시간 시간대는 UTC가 아니기 때문에 타임 라인의 일부 점입니다. 우리는 그것이 무엇인지 알 수 없습니다.)


를 a TIMESTAMP WITH TIME ZONE로 검색해도 아무런 문제가 없습니다 Instant. 둘 다 타임 라인의 한 지점을 UTC로 나타냅니다. Instant내 의견 OffsetDateTime으로는 더 많은 자체 문서화 가 선호 됩니다 .A TIMESTAMP WITH TIME ZONE는 항상 데이터베이스에서 UTC로 검색되고 A 는 항상 InstantUTC이므로 자연스럽게 일치하지만 OffsetDateTime다른 오프셋을 가질 수 있습니다.
Basil Bourque

@BasilBourque 불행히도, 현재 JDBC 사양, JPA 2.2 사양 및 PostgreSQL JDBC 설명서 OffsetDateTime는 매핑 된 Java 유형으로 만 언급 됩니다. Instance어딘가에서 비공식적으로 지원 되는지 확실하지 않습니다 .
ddekany

질문, 입력에 지정한 오프셋과 같은 무시 '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로 변환합니다. 여기서 날짜는 시간대가없는 타임 스탬프입니다. 시간대가있는 타임 스탬프의 주요 가치가 무엇인지 이해하고 노력하고 있습니다.
pk1m

@ pk1m 문제가 복잡합니다 ::timestamptz. 당신의 문자열을 변환하는 것이로 TIMESTAMP WITH TIME ZONE, 그리고 추가로 변환 될 때 WITHOUT TIME ZONE, 즉 (어쩌면 UTC입니다) 세션 시간대에서 본 그 순간의 "벽에 달력"하루 벽 시계 시간을 저장합니다. 여전히 지정되지 않은 오프셋 (영역 없음)이있는 로컬 타임 스탬프 만됩니다.
ddekany

파이썬으로 작업 중이며 타임 스탬프 인식 datettime 객체를 삽입 할 때 삽입됩니다. 시간대와 함께 타임 스탬프를 사용하는 것이 가치가 있지만 시간대를 처리 할 필요는 없습니다.
pk1m

12

여기 도움이 될만한 예가 있습니다. 시간대가있는 타임 스탬프가있는 경우 해당 타임 스탬프를 다른 시간대로 변환 할 수 있습니다. 기본 시간대가 없으면 올바르게 변환되지 않습니다.

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

5
"제대로 변환되지 않습니다는" 사실이 아니다. 무엇 timestamptimestamptz의미 하는지 이해해야합니다 . timestamptz"절대 시간 (UTC)" timestamp은 시계가 특정 시간대에서 보여준 것을 나타냅니다. 따라서 timestamptz시간대 로 변환 할 때이 절대 시점에서 시계가 뉴욕에서 무엇을 보여 주었습니까? 반면에 "변환" 할 때 뉴욕의 시계가 x를 표시했을 때 절대 시점이 무엇인지timestamp 묻고 있습니까?
fphilipe

AT TIME ZONE이미 이해하더라도 구조는, 자신의 티저 뇌입니다 WITH대의 WITHOUT TIME ZONE유형. 그것들을 설명하는 것은 호기심 많은 선택입니다. (: ( 타임 스탬프를 타임 스탬프 AT TIME ZONE로 변환 하고 그 반대도 마찬가지입니다. 정확히 알 수 없습니다.)WITH TIME ZONEWITHOUT TIME ZONE
ddekany

now()::timestamp AT TIME ZONE 'CST''CST'구역의 시계가 현지 시계가 현재 표시되는 시간을 어떤 순간에 표시 할 것인지를 제외하고는 의미가 없습니다.
Jasen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.