2017-12-14 4 views
5

누군가가 왜 그렇게 설명 할 수 있습니까? 왜 그 시간 동안 24 분 오프셋이 있고 어떻게 처리해야합니까?java.sql.Timestamp 잘못된 시간 파싱

스칼라 2.12 및 Java 8

scala> java.sql.Timestamp.valueOf("1900-01-01 00:59:00") 
res22: java.sql.Timestamp = 1900-01-01 00:59:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:00:00") 
res23: java.sql.Timestamp = 1900-01-01 01:24:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:14:00") 
res24: java.sql.Timestamp = 1900-01-01 01:38:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:20:00") 
res25: java.sql.Timestamp = 1900-01-01 01:44:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:23:00") 
res26: java.sql.Timestamp = 1900-01-01 01:47:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:24:00") 
res27: java.sql.Timestamp = 1900-01-01 01:24:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:30:00") 
res28: java.sql.Timestamp = 1900-01-01 01:30:00.0 
+0

로캘은 무엇입니까? 스칼라가없는 Java 8 만 사용하면 로케일 (en_US)에서이를 재현 할 수 없습니다. – rgettman

+1

@rgettman'ZoneId.systemDefault'는'Europe/Warsaw'를 반환합니다. –

+0

'System.setProperty ("user.timezone", "Europe/Warsaw");로 문제를 재현했습니다. ... ... 저에게 버그처럼 보입니다. 과거에는 시간대 버그가있었습니다. 해당 기간 동안 zoneinfo 데이터베이스에 가짜 전환이있는 것처럼 보이는 라이브러리 코드를 검토하십시오. 이것을 검증하는 데는 몇 가지 작업이 필요하며, 불행히도 지금은 시간이 없습니다. –

답변

4

은 IANA 시간대 데이터베이스에서 표준 시간대 정의에서 봐 : 폴란드 한 시간의 타임 존 오프셋 (offset)를 1900 년에

# Zone NAME   GMTOFF RULES FORMAT [UNTIL] 
Zone Europe/Warsaw 1:24:00 -  LMT  1880 
         1:24:00 -  WMT  1915 Aug 5 # Warsaw Mean Time 
         1:00 C-Eur CE%sT 1918 Sep 16 3:00 
         2:00 Poland EE%sT 1922 Jun 
         1:00 Poland CE%sT 1940 Jun 23 2:00 
         1:00 C-Eur CE%sT 1944 Oct 
         1:00 Poland CE%sT 1977 
         1:00 W-Eur CE%sT 1988 
         1:00 EU CE%sT 

을했고 UTC로부터 24 분, 즉 그들은 지역 평균 태양 시간을 사용하고있었습니다. 표준 표준 시간대가 1915 년 8 월 5 일에 도입되기 전이었습니다.

현지 시간대 (1시 24 분의 오프셋)로 해석되는 timestamp without time zone으로 피드해야합니다.

Somebody (scala?)는이 시간 소인을 현지 표준 시간대의 시간 소인으로 다시 변환하지만 실수로 한 시간의 오프셋을 사용합니다. 내가 그 문제를 해결하지만, 하나가 전체에 timestamp without time zone를 사용하거나 폴란드의 시간을 생각하는 구성 요소를 해결하는 방법을 정확히 모르는

내가 거기 말할 수있는 지금까지 1900

+0

올바른 예 : Java 8에서 1900 년의 전환에 대해 알지 못합니다. 1915 년에 가장 오래된 전환 : 전환 [1915-08-05T00 : 00 + 01 : 24에서 +01 : 00으로 중첩]입니다. –

+0

감사합니다. Java가 문제가되는 것처럼 보입니다. 그래서 남은 유일한 옵션은 '타임 스탬프로 타임 스탬프'를 피하는 것입니다. –

+0

저장 및 검색에'java.time.Instant' 만 사용할 수 있다면 (다른 모든 것이 실패하면'String'을 사용하지만'Instant'를 선호 할 것입니다) 데이터베이스에 타임 스탬프와 함께 timezone을 사용할 수 있다고 가정합니다. –

2

에서 UTC에서 1 시간 상쇄되었다 여기에 관련된 두 개의 버그. java.util.Date 클래스에서 둘 다 (내가 맞다면), 수퍼 클래스는 java.sql.Timestamp입니다.

처음에는 1900 년 바르샤바에서 시간 오프셋 전환이 없습니다. Java 8이 알고있는 가장 초기의 전환은 1915 년입니다. 따라서 바르샤바는 우리가 우려하는 모든 시간 동안 GMT에서 1시 24 분에 오프셋되었습니다 와.

내가 시도 :

TimeZone.setDefault(TimeZone.getTimeZone("Europe/Warsaw")); 
    ZoneOffset offset0124 = ZoneOffset.ofHoursMinutes(1, 24); 

    System.out.println("" + new Date(0, 0, 1, 0, 59) 
      + " -> " + new Date(0, 0, 1, 0, 59).toInstant().atOffset(offset0124)); 
    System.out.println("" + new Date(0, 0, 1, 1, 14) 
      + " -> " + new Date(0, 0, 1, 1, 14).toInstant().atOffset(offset0124)); 
    System.out.println("" + new Date(0, 0, 1, 1, 24) 
      + " -> " + new Date(0, 0, 1, 1, 24).toInstant().atOffset(offset0124)); 

이 인쇄 :

Mon Jan 01 00:59:00 CET 1900 -> 1900-01-01T01:23+01:24 
Mon Jan 01 01:38:00 CET 1900 -> 1900-01-01T01:38+01:24 
Mon Jan 01 01:24:00 CET 1900 -> 1900-01-01T01:24+01:24 

방법은 간접적으로 사용되지 않는 Date 생성자를 사용하여 사용 Timestamp.valueOf 방법, 그래서 내가 (내가 아닌 동일한 생성자입니다 아무런 차이가 없다고 생각하면서 초를 사용하지 않고 있습니다.) 나는뒤로 위의 세 가지 사례를 언급합니다 :

  • 1시 24분

    제대로 처리, 우리는 Date.toString()에서와 OffsetDateTime에서 모두의 예상 시간을 얻을.
  • 1:14는 24 분 후 1:38로 인식됩니다. 이것은 나에게 버그처럼 보입니다.
  • 0:59는 24 분 후에도 1:23으로 인식됩니다. 우리는 OffsetDateTime에서 이것을 볼 수 있습니다. 같은 버그. 그러나 Date.toString()은 예상대로 00:59를 생성합니다. 이것은 내가 어떻게해서든지 첫 번째 버그를 보완하는 두 번째 버그 인 것처럼 보입니다. 확인하지는 않았지만이 버그의 원인으로 인해 Timestamp.toString()이 올바르게 작동하지 않을 것으로 판단됩니다.

수표로 Timestamp 개체의 차이가 0:59와 1:24로 계산되었습니다. 원하는 결과는 25 분 또는 1 500 000 밀리 초입니다.코드는 :

System.out.println(java.sql.Timestamp.valueOf("1900-01-01 01:24:00").getTime() 
      - java.sql.Timestamp.valueOf("1900-01-01 00:59:00").getTime()); 

60000 

60초 1 분간과 동일하게 출력한다. 따라서 두 타임 스탬프가 우리가 예상했던대로 인쇄되었지만 여전히 버그가 있습니다.