후레임의 프로그래밍
왜 두 시간을 빼면 (1927년) 이상한 결과가 나오는 이유는 무엇입니까? 본문
질문
다음 프로그램을 실행하면 1 초 간격으로 시간을 참조하는 두 개의 날짜 문자열을 구문 분석하고 비교합니다.
public static void main(String[] args) throws ParseException {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str3 = "1927-12-31 23:54:07";
String str4 = "1927-12-31 23:54:08";
Date sDt3 = sf.parse(str3);
Date sDt4 = sf.parse(str4);
long ld3 = sDt3.getTime() /1000;
long ld4 = sDt4.getTime() /1000;
System.out.println(ld4-ld3);
}
출력은 다음과 같습니다.
353
왜 1
이 아니라 ld4-ld3
(1 초의 시간 차이에서 예상했듯이)이지만 353
?
날짜를 1 초 후 시간으로 변경하는 경우 :
String str3 = "1927-12-31 23:54:08";
String str4 = "1927-12-31 23:54:09";
그런 다음 ld4-ld3
는 1
이됩니다.
자바 버전 :
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)
Timezone(`TimeZone.getDefault()`):
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,
useDaylight=false,
transitions=19,
lastRule=null]
Locale(Locale.getDefault()): zh_CN
답변
상하이의 12 월 31 일 시간대 변경입니다.
See this page for details of 1927 in Shanghai. Basically at midnight at the end of 1927, the clocks went back 5 minutes and 52 seconds. So "1927-12-31 23:54:08" actually happened twice, and it looks like Java is parsing it as the later possible instant for that local date/time - hence the difference.
종종 이상하고 멋진 시간대의 또 다른 에피소드입니다.
수정 : 그만 누르세요! 역사 변경 ...
TZDB . 2013a에서 결과는 358 초이며 전환 시간은 23:54:08이 아니라 23:54:03입니다.
나는 Noda Time에서 단위 테스트 ... 이제 테스트가 변경되었지만 표시 될뿐입니다. 기록 데이터도 안전하지 않습니다.
수정 : 기록이 다시 변경되었습니다 ...
TZDB 2014f에서 변경 시간은 1900-12-31로 이동했으며 이제는 343 초에 불과합니다 (따라서 t
와 t + 1
사이의 시간
는 344 초입니다. 무슨 뜻인지 알 수 있습니다.
수정 : 1900 년 전환에 대한 질문에 답하기 위해 자바 시간대 구현은 모든 시간대를 단순히 표준 시간대로 취급하는 것 같습니다. 1900 UTC가 시작되기 전의 모든 순간 :
import java.util.TimeZone;
public class Test {
public static void main(String[] args) throws Exception {
long startOf1900Utc = -2208988800000L;
for (String id : TimeZone.getAvailableIDs()) {
TimeZone zone = TimeZone.getTimeZone(id);
if (zone.getRawOffset() != zone.getOffset(startOf1900Utc - 1)) {
System.out.println(id);
}
}
}
}
위의 코드는 내 Windows 컴퓨터에서 출력을 생성하지 않습니다. 따라서 1900 년 초에 표준 오프셋 이외의 오프셋이있는 모든 시간대는 전환으로 간주됩니다. TZDB 자체에는 그 이전으로 되돌아가는 일부 데이터가 있으며 "고정 된"표준 시간 (getRawOffset
이 유효한 개념이라고 가정하는 것)에 대한 아이디어에 의존하지 않으므로 다른 라이브러리가 필요합니다. 이 인공적인 전환을 도입합니다.
'스택오버플로우(Stack Overflow)' 카테고리의 다른 글
Java는 참조에 의한 전달(call by value)입니까 아니면 값에 의한 전달(call by reference)입니까? (0) | 2020.10.26 |
---|---|
원격 Git 브랜치를 어떻게 확인합니까? (0) | 2020.10.26 |
var functionName = function () {} vs function functionName () {} (0) | 2020.10.26 |
현재 Git 작업 트리에서 로컬 (추적되지 않은) 파일을 제거하는 방법 (0) | 2020.10.26 |
JavaScript에서 문자열에 하위 문자열이 포함되어 있는지 확인하는 방법은 무엇입니까? (0) | 2020.10.26 |