2011-05-12 2 views
4

일부 계산 루틴을 .Net에서 Java로 이식하지만 날짜 클래스에 정밀도 문제가있는 것 같습니다. 어쩌면 나는 이것에 관해서 눈이 멀었지만 왜 결과가 다른지 알 수 없다.DateTime 정밀도 차이 .NET 대 Java

플랫폼간에 동일한 숫자 (밀리 초)를 얻으려면 날짜를 어떻게 처리해야합니까?

닷넷

[Test] public void foo() { 
    DateTime dt1 = new DateTime(2011, 2, 26, 19, 25, 24); 
    DateTime dt2 = new DateTime(2011, 2, 28, 18, 40, 25); 
    double millis = (dt2 - dt1).TotalMilliseconds; 
    Assert.AreEqual(170101000, millis); 
} 

자바

@Test public void foo() throws Exception { 
    Date d1 = createDate(2011, 2, 26, 19, 25, 24); 
    Date d2 = createDate(2011, 2, 28, 18, 40, 25); 
    long millis = d2.getTime() - d1.getTime(); 
    Assert.assertEquals(166501000, millis, 0.01); 
} 

private static Date createDate(int year, int month, int day, 
     int hour, int minute, int second) { 
    Calendar instance = Calendar.getInstance(); 
    instance.clear(); 
    instance.set(year, month, day, hour, minute, second); 
    return instance.getTime(); 
} 
+0

형식이 다르거 나 다른 값을 반환한다고합니다. 그들이 다른 값을 반환한다면, 그것은 그들이 몇 밀리 초 간격으로 움직이고 있기 때문일 수 있습니까? – soandos

+0

Java에서 Java Date를 사용하지 마십시오. Joda Date를 사용하십시오. – bwawok

+0

Noda Time은 .NET 용으로 완성 되었습니까? 누군가 Joda 시간의 .NET 포트에서 작업하고 있다는 것을 알고 있습니다 ... – David

답변

8

Wonderful!

문제 :

Java Calendar months start at 0.Net Datetime months start at 1.

.NET 2 월과 Java 3 월을 비교합니다. 그리고 Arjan이 제안한 것처럼 3 월 27 일에는 많은 시간대에서 일광 절약 시간제로 변경되었습니다.

Java 캘린더를 사용할 때 매우 일반적인 문제입니다. 이를 피하려면 다음과 같이 몇 개월 동안 명명 된 상수를 사용해야합니다.

Date d1 = createDate(2011, Calendar.MARCH, 26, 19, 25, 24); // Calendar.MARCH == 2 
+0

실제로 문제가되는 것 같습니다. 몇 달 동안 0 - 11을 사용하면 쉽게 실수로 이어질 수 있습니다. 그것은 나를 속였습니다. – Arjan

0

당신은 문제가 날짜 시간 구조가 아닌 이중 구조에 확실합니까? documentation on the .NET Double data type에서 :

정밀

가치와 의 손실 부동 소수점 부동 소수점 숫자 만 부동 소수점 숫자의 정밀도를 결정하는 소수 수를 대략, 수 기억 얼마나 정확히 그 숫자는 십진수에 가깝습니다. 기본적으로 Double 값에는 자릿수가 내부적으로 유지되지만 십진수 15 자리가 포함됩니다. 당신이 분수 밀리 초를 반환하지 않는 때문에, 당신은 System.Int64 (긴 C#에서) 데이터 유형을 사용할 수 있습니다

: 부동 소수점 숫자 의 정밀도는 여러 가지 결과를 초래한다. 값이 해당 데이터 유형의 허용 범위 내에 있습니다. Int32 (long)에 대한 max value은 9,223,372,036854775807

-1

입니다. 이는 빼는 방식에서 비롯된 것입니다. java에서는 시간을 나타내는 2 개의 long을 뺍니다. 당신이 오래 전으로 거슬러 올라간다면 날짜로 바꾸십시오. 원래대로 설정하지 않았을 수도 있습니다. 소수점 이하로 약간의 손실이 있기 때문입니다. .net에서 실제 날짜를 뺀 다음 밀리 초로 변환합니다. 따라서이 결과는 실제로 더 정확합니다. 당신이 .net에서 시간을 전체 miliseconds로 변환한다면, 나는 당신이 훨씬 더 가까운 결과를 찾을 것이라고 확신 할 것이다.

+0

누군가가 아래쪽 투표를 설명합니까? – Chad

1

밀리 초의 차이는 3,600,000이므로 정확히 1 시간입니다. 한 언어에서 다른 표준 시간대 설정을 사용하고있는 경우, DST와 DST간에 변경이있는 경우 일 수 있습니까?

나는 더 많은 테스트를했습니다. PHP 결과는 C# 결과 (밀리 초 대신 초만 나타남)와 일치하고 Java 결과는 Java 결과와 일치합니다. 이 문제는 Java에서 시간대 처리의 버그로 보입니다. Java에 따르면 두 번째 시간은 DST에 있으며, 이는 제 시간대 (유럽/암스테르담)에서 올바르지 않습니다.

0

혼란 스럽습니다. 두 번째 테스트 (Java)가 통과되었다고 말하는가? 실제로 첫 번째 (C#) 테스트와 같은 번호가 있기 때문에 : 170101000.

여기가 내 테스트 (합격)입니다. 나는 날짜와 캘린더의 대안으로 JodaTime 객체를 던졌다 :

@Test public void foo() throws Exception { 
    DateTime dt1 = new DateTime(2011, 2, 26, 19, 25, 24, 0); 
    DateTime dt2 = new DateTime(2011, 2, 28, 18, 40, 25, 0); 
    Duration d = new Duration(dt1, dt2); 
    Assert.assertEquals(170101000, d.getMillis(), 0.01); 
    Date d1 = createDate(2011, 2, 26, 19, 25, 24); 
    Date d2 = createDate(2011, 2, 28, 18, 40, 25); 
    long millis = d2.getTime() - d1.getTime(); 
    Assert.assertEquals(170101000, millis, 0.01); 
} 

private static Date createDate(int year, int month, int day, 
     int hour, int minute, int second) { 
    Calendar instance = Calendar.getInstance(); 
    instance.clear(); 
    instance.set(year, month, day, hour, minute, second); 
    return instance.getTime(); 
} 
+0

현재 시간대는 무엇입니까? – Arjan

+0

@Arjan : JodaTime의 DateTimeZone.getDefault(). toString()은 내 시스템에서 "America/Los_Angeles"입니다. – ccoakley

+0

그 이유는 당신이 문제가없는 이유를 설명합니다. DST는 3 월 27 일에 시작하지 않으므로 모든 계산이 올바르게 수행됩니다. 문제를 재현하려면 지정된 일에서 14를 빼십시오 (따라서 26에서 12로, 28에서 14로 변경하십시오). – Arjan