2016-12-02 7 views
2

GregorianCalendar의에서 날짜를 얻는 것은 일관성이되고있는이 각각 GMT + 1 2000-01-01 자정, GMT + 1, UTC를 나타냅니다는 GregorianCalendar를

946681200000, 946681200000, 946684800000 

에서

Calendar cal = new GregorianCalendar(2000, 0, 1); 
long testCalOne = cal.getTimeInMillis(); 
cal.setTimeZone(TimeZone.getTimeZone("UTC")); 
long testCalTwo = cal.getTimeInMillis(); 

Calendar cal2 = new GregorianCalendar(2000, 0, 1); 
cal2.setTimeZone(TimeZone.getTimeZone("UTC")); 
long testCalThree = cal2.getTimeInMillis(); 

System.out.println(testCalOne + ", " + testCalTwo + ", " + testCalThree); 

결과 . 내 시간대는 UTC 기준으로 +1 시간입니다.

여기서 문제는 getTimeInMillis가 1970-01-01부터 UTC로 밀리 초를 반환해야한다는 것입니다. testCalThree 만 정확합니다.

또 다른 문제는 이전에 getTimeInMillis를 호출했는지에 따라 setTimeZone이 작동하지 않는 것입니다.

내 목표는 다른 코드에서 매개 변수로받는 Calendar를 가져 와서 이후 사용을 위해 UTC (java.util) Date를 얻는 것입니다.

+1

정상 상태를 유지하려면 JodaTime 또는 Java8 새 날짜/시간 API로 전환하십시오. – lexicore

+0

여전히 '캘린더'를 사용하는 이유는 무엇입니까? (불쾌감 없음) – Spotted

+0

내 코드가 아니며 매개 변수를 가져옵니다. – Juryt

답변

0

나는 Calendar 구현의 버그라고 생각합니다. time이 캐시됩니다. 즉, 계산 한 경우이 아닌 한 을 다시 사용합니다.

하지만 어떻게 든 설정 시간대가 관련 변경으로 인식되지 않습니다.

일부 필드를 명시 적으로 변경하거나 지우면 강제로 다시 계산할 수 있습니다 (ms). 그래서이 :

Calendar cal = new GregorianCalendar(2000, 0, 1); 
    long testCalOne = cal.getTimeInMillis(); 
    cal.clear(Calendar.ZONE_OFFSET); 
    cal.setTimeZone(TimeZone.getTimeZone("UTC")); 
    long testCalTwo = cal.getTimeInMillis(); 

    Calendar cal2 = new GregorianCalendar(2000, 0, 1); 
    cal2.setTimeZone(TimeZone.getTimeZone("UTC")); 
    long testCalThree = cal2.getTimeInMillis(); 

    System.out.println(testCalOne + ", " + testCalTwo + ", " + testCalThree); 

을 제공합니다 :

946681200000, 946684800000, 946684800000 

사용자가 예상하는대로. 시간대를 설정하기 전에해야 할 일은 cal.clear(Calendar.ZONE_OFFSET)입니다.

어쨌든, 나는 의견에서 권고를 반복하고 싶습니다. 정신을 소중히 생각한다면 JodaTime 또는 Java8 날짜/시간으로 전환하십시오.

+0

기술적으로는 getTimeInMillis가 오프셋을 고려하여 UTC로 반환해야하기 때문에 기술적으로는 예상대로 아닙니다. 따라서 시간대 설정은 관련성이 없어야합니다. 그러나 getTimeInMillis가 도청되어 타임 존 변경 관련성이 있습니다. 답변 해 주셔서 감사합니다. – Juryt

+0

시간대 설정은 어떻게 관련이 없습니까? 'getTimeInMillis()'는 1970-01-01 00:00:00 UTC와 달력 인스턴스의 날짜 사이의 밀리 초를 반환합니다. 달력에 _local_ date 2000-01-01 00:00:00이 들어 있기 때문에 시간대를 설정하는 것이 중요합니다. 2000-01-01 00:00:00 UTC는 2000-01-01 00:00:00 UTC + 1과 다릅니다. – Archie

0

추가로 생각하면 코드가 의도 한대로 작동 할 수 있습니다. setTimeZone은 getter가 달력에서 호출되었는지 여부에 따라 다르게 작동 할 수 있습니다.

첫 번째 경우에는 시간대가 변경되지만 시간은 이미 초기화되어 초기화되므로 UTC 시간은 변경되지 않습니다. 두 번째 경우

, 그것은 우리가 생성자에 전달 2001년 1월 1일의 초기화 날짜는 UTC 시간이었다 UTC보다는 지역의 시간대로 해석해야 함을 나타냅니다.

그렇다면 결과가 의미가 있습니다.

+0

이것은 말도 안됩니다. * getter *를 호출하는 순간은 완전히 무관해야합니다. 나는 이것이 버그라고 생각한다. – lexicore

+0

내부적으로 일정이 느립니다. 필요한 경우 내부 필드 만 계산합니다. 그러나 직접 설정할 수는 있습니다. 이것은 제가이 수업에서 여러분이 getter를 호출하면 관련성이 있다고 의심하게됩니다. (그러나 반대 직관적이고 clunky.) – Juryt

0

TL; DR

myGregCal.toZonedDateTime() 
     .toInstant() 

... 나 ...

java.util.Date.from(
    myGregCal.toZonedDateTime() 
      .toInstant() 
) 

java.time는

내 목표는 내가 다른 코드에서 매개 변수로받는 일정을과를 얻을 수 있습니다 UTC (java.util) 추가 사용 날짜.CalendarDate

성가신 오래된 날짜 - 시간의 수업은 이제 java.time 클래스에 의해 대체 유산이다. 다행스럽게도 이전 클래스에 대한 새 메소드를 호출하여 java.time으로 /로부터 변환 할 수 있습니다.

ZonedDateTime zdt = myGregCal.toZonedDateTime() ; 

Instant을 추출하십시오. 이 클래스는 시간 단위로 UTC (나노초 단위)의 순간을 나타냅니다.

Instant instant = zdt.toInstant() ; 

표준 ISO 8601 형식의 해당 UTC 값을 나타내는 String를 생성하려면, toString를 호출합니다.

String output = instant.toString() ; 

당신은보다 유연한 OffsetDateTime로 변환하고 DateTimeFormatter를 사용하여 생성 된 문자열에서 다른 형식이 필요합니다. 많은 예제에서 스택 오버플로를 검색하십시오.

Date 클래스를 피하는 것이 가장 좋습니다. 그러나해야한다면, 개종하십시오. Instant처럼 Date은 타임 라인상의 포인트를 UTC로 나타냅니다. 그러나 Date은 밀리 초 단위로 제한됩니다. 그래서 위험 데이터 손실, 9 자리의 나노초 대 3 자리 밀리 초를 초과하는 초의 소수 부분에서 숫자를 제거하는 것입니다. java.time

소개

java.util.Date utilDate = Date.from(instant) ; 

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과 같은 유용한 클래스가 있습니다.