2016-09-12 4 views
5

자바 시간의 처리와 혼동 스럽습니다. 필자는 타임 스탬프가 zulu 시간으로 지정되면 java가 현지 시간과 관련하여 오프셋을 처리한다는 가정하에 오랫동안 작업했습니다.자바와 혼란 UTC 시간 분석하기

설명해주십시오. 현재 UTC +1의 오프셋을 가진 BST입니다. 염두에두고,이 줄루어 시간을 기대 :

2016-09-12T13:15:17.309Z 

그것을 구문 분석 후

2016-09-12T14:15:17.309 

LocalDateTime 될 수 있습니다. 이것은 기본 시스템 시간이 BST로 설정되고 위의 시간 소인 (zulu 시간)이 UTC 시간임을 지정하기 때문입니다.

 String ts = "2016-09-12T13:15:17.309Z"; 
     LocalDateTime parse = LocalDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME); 
     System.out.println(parse); 

이 인쇄됩니다 :

대신 그러나이 샘플을 고려

2016-09-12T13:15:17.309 

은 그래서 LocalDateTime로 구문 분석 타임 스탬프는, UTC 시간으로 인식되지 않는 대신 직접의 현지로 취급. 그래서 나는 아마도 올바른 로컬 시간을 얻기 위해 그것을 ZonedDateTime으로 구문 분석하고 LocalDateTime으로 변환해야한다고 생각했습니다. 이 테스트로 : 두 날짜

2016-09-12T13:15:17.309Z 
2016-09-12T13:15:17.309 

같은 출력 :

 String ts = "2016-09-12T13:15:17.309Z"; 
     ZonedDateTime parse = ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME); 
     System.out.println(parse); 
     System.out.println(parse.toLocalDateTime()); 

나는 출력을 얻을.

올바르게 내가 찾을 수있는이 구문을 분석 할 수있는 유일한 방법입니다 :

String ts = "2016-09-12T13:15:17.309Z"; 
    Instant instant = Instant.parse(ts); // parses UTC 
    LocalDateTime ofInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); 
    System.out.println(instant); 
    System.out.println(ofInstant); 

이 인쇄 : 올바른

2016-09-12T13:15:17.309Z 
2016-09-12T14:15:17.309 

.

그래서 질문 (들)은 다음과 같습니다

  • 자바 시간은 UTC 타임 스탬프를 인식하고 올바른 시스템 기본값으로 구문 분석하지 않나요?
  • LocalDateTime#parse 접근 방식을 사용하여 올바른 결과를 얻으려면 어떻게해야합니까?
  • 지금 모든 항목에 Instant을 사용해야하며 파싱을 취소해야합니까?

문제는 jersey/jackson의 자바 시간 모듈은 ISO 포맷 LocalDateTime#parse 일반적인 방법을 사용하여 타임 스탬프를 분석한다는 것이다. 나는 그들이 실제로 줄루 (Zulu) 시간에있는 동안 LocalTime으로 대우되고 있기 때문에 나의 시간은 싫은 것이 아니라는 것을 깨달았다.

답변

5

LocalDateTime의 목적을 오해하고 있습니다.

는 ISO-8601 달력 시스템의 시간대없는 날짜 - 시간과 같은 {2007-12-03T10 @code : 15 : 30}

클래스 문서를 인용합니다.

...

이 클래스는 저장 또는 시간대를 나타내지 않습니다. 대신 생일에 사용 된 날짜에 대한 설명이 벽 시계에 표시된 현지 시간과 결합됩니다. 오프셋이나 시간대와 같은 추가 정보없이 타임 라인에서 순간을 나타낼 수 없습니다.

는 그래서 명시 적 목적은 단지 시간 영역없이 날짜와 시간 을 표현하는 것입니다이다. 시간대는 이 아니며 을 나타내는의 현지 시간대의 날짜와 시간을 나타내지는 않습니다.

따라서 각 변환은 표준 시간대를 제거합니다.

따라서 세 번째 예제에서 이미 사용한대로 ZonedDateTimeZoneId.systemDefault()이 필요합니다. 두 번째 예를 들어

이 될 수있다 :

String ts = "2016-09-12T13:15:17.309Z"; 
ZonedDateTime parse = 
    ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME) 
     .withZoneSameInstant(ZoneId.systemDefault()); 
System.out.println(parse); 
System.out.println(parse.toLocalDateTime()); 
+0

예제가 예 3과 즉시 대화를하는 것처럼 보입니다. 맞습니다. LocalDateTime이 의미하는 바를 오해했습니다. 시간대 :) 감사합니다 – pandaadb

+0

아, 그래서 ZonedDateTime은 "Z"로 자동으로 (내가 원하는 것) UTC로 해석하는 시간대를 인식합니다 - 맞습니까? – pandaadb

+0

@pandaadb 그래, 이걸 쓰는 또 다른 방법 일거야. –

3

TL; DR

예 :

Instant.parse("2016-09-12T13:15:17.309Z") 
     .atZone(ZoneId.of("Europe/London")) 
     .toString(); 

2016-09-12T14 : 15 : 17.309 + 01 : 00 [유럽/런던]

Run in IdeOne.com .

세부

Answer by Krüske가 올바른지. LocalDateTime 클래스의 의미를 오해합니다. 이 아니기 때문에 특정 지역의 날짜 - 시간을 나타냅니다.이 아닙니다. 그 반대의 경우는 이 아니며은 실제 순간을 나타냅니다.

Instant을 java.time의 기본 빌딩 블록 클래스로 생각해보십시오. Instant 클래스는 nanoseconds (소수 자릿수 9 자릿수까지)의 해상도로 UTC의 타임 라인에있는 순간을 나타냅니다.

입력 문자열은 구문 분석 및 문자열 표현 생성 모두에 대해 Instant 클래스에서 기본적으로 사용되는 ISO 8601 형식을 준수합니다. 끝에있는 ZZulu의 약자이며 UTC를 의미합니다. 서식 지정 패턴을 지정할 필요가 없습니다.

Instant instant = Instant.parse("2016-09-12T13:15:17.309Z"); 

프로그래머는 주로 UTC로 생각하고 작업하는 법을 배워야합니다. 자신의 시간대를 잊어 버려라. UTC를 하나의 진정한 시간으로 생각하십시오. 대안으로 시간대를 적용하고 필요한 경우에만 시간대를 적용하십시오.

America/Montreal, Africa/Casablanca 또는 Pacific/Auckland 같이 continent/region의 형식으로 지정 proper time zone name. BST 또는 EST 또는 IST과 같은 3-4 문자 약어는 표준 시간대가 아니며 고유하지 않으므로 사용하지 마십시오 (!). BST으로 영국 여름 시간을 의미하는 경우 실제 시간대 이름은 Europe/London입니다. java.time 클래스는 일광 절약 시간 (DST)을 포함하여 모든 예외를 조정하는 방법을 결정합니다. java.time

소개

ZoneId z = ZoneId.of("Europe/London"); 
ZonedDateTime zdt = instant.atZone(z); 

java.time 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 java.util.Date, Calendar, & SimpleDateFormat과 같이 문제가있는 이전 legacy 날짜 - 시간 클래스를 대체합니다.

Joda-Time 프로젝트는 지금 maintenance mode에, java.time로 마이그레이션을 조언한다.

자세히 알아 보려면 Oracle Tutorial을 참조하십시오. 그리고 많은 예제와 설명을 위해 스택 오버플로를 검색하십시오. 사양은 JSR 310입니다.

어디에서 java.time 클래스를 얻을 수 있습니까?

  • Java SE 8SE 9 이후
    • 내장한다.
    • 번들로 구현 된 표준 Java API의 일부입니다.
    • Java 9에는 몇 가지 사소한 기능과 수정 사항이 추가되었습니다.
  • Java SE 6 및 java.time 기능의 대부분
  • Android
    • ThreeTenABP 프로젝트 적응 ThreeTen - 백 포트 구체적 안드로이드 (상술 한).
    • How to use…을 참조하십시오.

ThreeTen-Extra 프로젝트는 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 향후 java.time에 추가 될 수있는 가능성을 입증합니다.여기에 Interval, YearWeek, YearQuartermore과 같은 유용한 클래스가 있습니다.