日期时间精度差异 .NET 与 Java

本文关键字:NET Java 时间 精度 日期 | 更新日期: 2023-09-27 17:56:10

我将一些计算例程从.Net移植到Java,但是Date类中似乎存在一些精度问题。也许我对此视而不见,但我无法弄清楚为什么结果不同。

我应该如何处理日期以跨平台获得相同的数字(毫秒)?

。网

[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();
}

日期时间精度差异 .NET 与 Java

太好了!

问题:

Java 日历月份从 0 开始,.Net 日期时间月份从 1 开始。

所以你正在比较.Net二月和Java三月。而且,正如 Arjan 所建议的那样,3 月 27 日是许多时区夏令时的变化。

这是使用 Java 日历时非常常见的问题。为了避免这种情况,您应该像这样对月份使用命名常量:

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

以毫秒为单位的差异是 3,600,000,所以正好是 1 小时。可能是一种语言使用的时区设置与另一种语言不同,其中 DST 有变化?

我做了更多的测试。PHP 结果与 C# 结果匹配(只有我得到秒而不是毫秒),我的 Java 结果与您的 Java 结果匹配。问题似乎是 Java 中时区处理中的错误。根据Java的说法,第二次是DST,这在我的时区(欧洲/阿姆斯特丹)是不正确的。

您确定问题出在 DateTime 结构中而不是在 Double 结构中吗? 来自有关 .NET Double 数据类型的文档:

浮点值和损失 精度

请记住,浮点数只能近似于小数 数字,并且精度为 浮点数确定如何 准确地说,这个数字近似于 十进制数。默认情况下,双精度 值包含 15 个十进制数字 精度,尽管最大为 17 数字在内部维护。这 浮点数的精度 有几个后果:

由于不返回小数毫秒,因此可以使用 System.Int64(在 c# 中为 long)数据类型。 您的值在该数据类型的允许范围内。 Int64(长整型)的最大值为 9,223,372,036,854,775,807

我很困惑。你是说第二个(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();
}

它来自你减法的方式。 在 java 中,您减去 2 个表示时间的长整型。 如果您从长回日期进行转换,则可能不是您最初设置的转换,因为小数点后位会有一些损失。 在 .net 中,您将减去实际日期,然后转换为毫秒。 所以这个结果实际上会更精确。 如果您将 .net 中的时间转换为总毫秒,那么减去我敢打赌您会发现更接近的结果。