2012-11-07 1 views
2

Calendar.set()을 사용하여 주어진 날짜 값에 대한 시간의 시작을 반환하는 코드가 있습니다.Java Calendar : 표준시로 오전 1시 전환 (DST에서)

public void testStartOfHourDST1() { 

    Calendar cal = Calendar.getInstance(); 

    long time = 1352005200000L; // Nov 4, 2012, 1AM EDT 
    cal.setTimeInMillis(time); 

    cal.set(Calendar.MILLISECOND, 0); 
    cal.set(Calendar.SECOND, 0); 
    cal.set(Calendar.MINUTE, 0); 

    System.out.println(new Date(time)); 
    System.out.println(new Date(cal.getTimeInMillis())); 
    System.out.println(System.getProperty("java.version")); 

    assertEquals(cal.getTimeInMillis(), time); // fails 

    return; 
} 

OUPUT :

일 11월 4일 01:00:00 EDT 2012

을 - (EDT EST로 전환 동부 시간대) 나는 일요일 11 월 4, 2012에 다음과 같은 문제가 발생 일 11월 4일 동부 표준시 01시 00분 0초 2012

1.6.0_35

Perha 추신 : 이것은 캘린더를 사용하는 올바른 방법이 아니지만 다음 시간 (또는 이전 시간)에 대해 동일한 테스트를 실행해도 문제가 없습니다. 이것이 JVM 문제입니까?

감사

답변

5

그것은 그것을 결정하고 그것을 수행하도록 프로그램 된 일을한다는 의미에서, 정말 문제가 아니다. 그것은 당신이 그것이 두 1am 중 빠른 것을 선택하는 것이 좋습니다면 문제입니다!

캘린더의 입력란을 변경 한 후에는 "1am in US/Eastern"입니다. 글쎄, 당신의 시간대는 하루에 두 개의 1am을 가지고 있었는데 어느 것이 선택해야합니까? OpenJDK의 저자는이 모호성을 제시 할 때 표준 시간대에 항상이를 나중에 해석 할 것이라고 결정했습니다. 이 의견은 java.util.GregorianCalendar의 오픈 JDK 6에서입니다 : 당신이 숫자의 실제 값을 출력 할 경우 cal.getTimeInMillis() 실제로 time의 값에서 시간으로 변경되었습니다 볼 수

// 2. The transition out of DST. Here, a designated time of 1:00 am - 1:59 am 
    // can be in standard or DST. Both are valid representations (the rep 
    // jumps from 1:59:59 DST to 1:00:00 Std). 
    // Again, we assume standard time. 

.

+0

좋은 점. 따라서 Calendar는 setTime/setTimeInMillis를 사용하거나 @Nambari에서 언급 한 setTimeZone을 사용하는 경우를 제외하고이 두 개의 겹치는 시간을 모호하게하는 방법을 지원하지 않습니다. – monex0

+0

캘린더가 _ 최근의 시간 _을 사용하고 있거나 기본 시간대를 적용하고 있습니까? 달력이 생성 될 때 (일광 절약 시간 전환이 발생한 후 프로그램이 실행될 경우 EST가됩니다) ... 대답을 모른다. – jahroy

+0

@jahroy java.util 그레고리 안 캘린더 (GregorianCalendar)는 임의적 인 대회의 일광 절약 시간이 아닌 표준 시간으로 항상 그 날의 1 : 00-1 : 59를 해석 할 것임을 나타냅니다. "... 여기, 오전 1시 - 오전 1시 59 분은 표준 또는 DST 일 수 있으며 둘 다 유효한 표현입니다 (DST는 1:59:59 DST에서 1:00:00 표준으로 점프 함). 다시 표준 시간을 가정합니다. " – Affe

0

정확한 시간대 가져 오기는 매우 중요합니다. 예를 들어, 시스템의 현재 시간 (밀리 초 단위)은 1970 년 1 월 1 일 자정부터 측정 된 것입니다. 이는 잘 설명되어 있습니다. 날짜 생성자의 JavaDoc 말한다 :

공개 날짜 (긴 날짜)

는 Date 객체를 할당하고 "를 시대로 알려진 표준 기본 시간 이후의 지정된 밀리 초 를 나타내도록 초기화 "즉 1970 년 1 월 1 일 00:00:00 GMT입니다. 괜찮지 만, 조금 어려운이 프로그램의 출력을하게

처음에는 이해하기 :

import java.util.Date; 
import java.util.TimeZone; 
import java.text.SimpleDateFormat; 

public class Demo { 
    public static void main(String[] args) { 
     TimeZone tz = TimeZone.getTimeZone("Europe/London"); 
     Date d = new Date(-3600000); 

     SimpleDateFormat df = new SimpleDateFormat("MMMM dd, yyyy HH:mm:ss.SSS z"); 
     df.setTimeZone(tz); 
     System.out.println(String.format("%8dms -> %s", 
        Long.valueOf(d.getTime()) ,df.format(d))); 

     d.setTime(0); 
     System.out.println(String.format("%8dms -> %s", 
        Long.valueOf(d.getTime()) ,df.format(d))); 
    } 
} 

출력은 다음과 같습니다

-3600000ms -> January 01, 1970 00:00:00.000 GMT 
     0ms -> January 01, 1970 01:00:00.000 GMT 

당신이 볼 수 있듯이, 시대를 분명히 1 시간 남았 어!

제외하지 않습니다. "GMT"표준 시간대를 명시 적으로 사용하면 모두 정상입니다. "유럽/런던"표준 시간대는 이와 같이 까다 롭습니다.

캘린더를 사용하는 경우 사용중인 시간대 또는 걸려있는 시간대를 이해하십시오.

+0

정보를 제공해 주지만 이 예제는 다소 혼란 스럽습니다. matting은 다른 시간대에 대해 'GMT'를 인쇄합니다. 'Z'출력 형식을 사용하면 +0100이 표시됩니다 (이는 분명합니다). 그래서 당신의 예제에서 문제는 유럽/런던이 '까다로운'것이 아니라, 문자열 출력이 모호하다는 것입니다. 내 실수는 set() 함수가 Calendar가 처음부터 UTC 시간을 재평가하도록 (그리고 따라서 사용하는 '1am'을 알아 내야하는 것 사이에 혼란을 겪게 됨) 깨닫지 못하는 것입니다. 원래 문제는 DST 오프셋을 지원하는 시간대에서만 발생합니다. – monex0