评估时铸造和之后铸造之间的差异

  • 本文关键字:之间 评估 之后 java gwt
  • 更新时间 :
  • 英文 :


我刚刚在我正在开发的一个网站上发现了一个错误,我纠正了它。我的问题是,即使我纠正了,我也不明白问题出在哪里。

我有两个日期(我不能使用GregorianCalendar),我想用天来评估这两个日期之间的距离。这有点琐碎,但我的代码有一个奇怪的行为。

对于特定的日期,例如:2008年4月26日和2008年5月26日,天数应该正好是30天,但我得到了-19天。对于其他日期,它运行良好。以下是我所做的:

    Date dMin = ... // -> 26/04/2008
    Date dMax = ... // -> 26/05/2008
    System.out.println((dMax.getTime()-dMin.getTime())/(1000*60*60*24)); // prints 30
    int i = (int) (dMax.getTime()-dMin.getTime())/(1000*60*60*24); // i = -19

那么我是如何纠正的呢?我做了这样的事:

long i = (dMax.getTime()-dMin.getTime())/(1000*60*60*24);

后来,就在我把它显示在屏幕上之前,我会把它转换成一个整数,它运行得很好。

我正在使用GWT,这个演算是在客户端完成的(所以它被编译为javascript)。

那里有我遗漏的东西吗?我想是的,但我找不到它是什么。

我认为您的强制转换(括号)有问题,例如:

public static void main(String[] args) throws Exception {
    System.out.println((int)(1.2)*10); //prints 10
    System.out.println((int)(1.2*10)); //prints 12
}

因此,int i = (int) (dMax.getTime()-dMin.getTime())/(1000*60*60*24); // i = -19在除法之前首先将dMax.getTime()-dMin.getTime()强制转换为int,可能会出现溢出。

Date.getTime()返回long。一个月是(24*60*60*1000*30=)2592000000毫秒。这个值需要32位,因此它不适合无符号整数(其最高值为231-1)。因此,当您在将dMax.getTime()-dMin.getTime()除以1000*60*60*24之前将其强制转换为int时,会出现无声溢出错误,截断的结果将被解释为负的int值。

除法之后,结果已经足够小,可以放入int,因此在强制转换时没有溢出,最终结果是正确的。

Joda时间

如果您使用一个好的日期时间库,如JodaTime或JSR310/Java 8,这种工作会更容易、更可靠。

示例代码

以下是Java 7中Joda Time 2.3中的一些示例代码。

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime start = new DateTime(2008, 4, 26, 0, 0, 0, timeZone);
DateTime stop = new DateTime(2008, 5, 26, 0, 0, 0, timeZone);
int daysBetween = Days.daysBetween( start, stop ).getDays();

转储到控制台…

System.out.println( "start: " + start );
System.out.println( "stop: " + stop );
System.out.println( "daysBetween: " + daysBetween );

执行时…

start: 2008-04-26T00:00:00.000+02:00
stop: 2008-05-26T00:00:00.000+02:00
daysBetween: 30

最新更新