4

我有非常简单的代码来计算两次之间的差异:

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

public class JavaApplication8 {
    private static final SimpleDateFormat timeFormat = new SimpleDateFormat("hh:mm:ss.SSS");

    public static void main(String[] args) throws InterruptedException {
        Date start = GregorianCalendar.getInstance().getTime();
        Thread.sleep(100);
        Date end   = GregorianCalendar.getInstance().getTime();

        long diff = end.getTime() - start.getTime();
        System.out.println(timeFormat.format(diff));
    }
}

但它打印01:00:00.100而不是00:00:00.100,为什么?

4

4 回答 4

5

解决此问题的其他方法。实际上,您拥有的时间差异不是当前时间的毫秒数。它只是时间差异,所以做一个简单的划分,你可以有小时:分钟:秒。而且速度相当快。

Date start = GregorianCalendar.getInstance().getTime();
        Thread.sleep(100);
        Date end = GregorianCalendar.getInstance().getTime();

        long longVal = end.getTime() - start.getTime();

        long hours = longVal / 3600000;
        long mins = (longVal % 3600) / 60000;
        long secs = longVal % 60000;

        System.out.println(hours + " " + mins + " " + secs);
于 2013-08-07T14:50:58.473 回答
4

你混淆了两个概念:

  • 您正在测量时间间隔(两个时间点之间的差异)
  • 您正在打印日期(一个时间点)

两者不兼容,你总会得到这样奇怪的效果。在您的情况下,正如其他评论所指出的那样,时区混入其中。时区的概念仅适用于日期(时间点),但对于间隔没有意义。

您可以使用 Jodatime 库或 JSR 310:日期和时间 API(我认为是 Java 8 附带的)。

使用 Jodatime,您可以明确地构造一个区间:

DateTime start = new DateTime(2004, 12, 25, 0, 0, 0, 0);
DateTime end = new DateTime(2005, 1, 1, 0, 0, 0, 0);
Period period = new Period(start, end);

然后用 PeriodFormatter 格式化它

PeriodFormatter daysHoursMinutes = new PeriodFormatterBuilder()
   .appendDays()
   .appendSuffix(" day", " days")
    .appendSeparator(" and ")
    .appendMinutes()
    .appendSuffix(" minute", " minutes")
    .appendSeparator(" and ")
    .appendSeconds()
    .appendSuffix(" second", " seconds")
    .toFormatter();

System.out.println(daysHoursMinutes.print(period));

通过分离一个时间点和两个时间点之间的时间的概念,您可以确保没有任何其他意外(例如闰秒)。

于 2013-08-07T15:07:35.333 回答
4

这是时区问题。DateFormat.format()默认情况下,将在您的默认时区格式化日期,这似乎是UTC+1.

您应该将时区设置timeFormatUTC

timeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(timeFormat.format(diff));

此外,您应该在 DateFormat 中使用HH而不是。是 12 小时制。hhhh

new SimpleDateFormat("HH:mm:ss.SSS");

更新 :

但还有其他一些重大问题。目前您正在尝试格式化持续时间,您不应该这样做。Java Date API,没有任何周期或持续时间的概念。

您从格式化中获得的值只不过是从纪元开始的毫秒数(相当于差异)。Date相反,它返回一个对象。虽然结果可能看起来正确,但从技术上讲,两个日期之间的差异表示一个时期或持续时间,这与 Date(表示特定时间的瞬间)不同。

您应该考虑将这项任务转移到Joda Time,它有代表这些概念的类Period,如Instant、 和Duration

于 2013-08-07T14:37:56.840 回答
0

因为您的时区是 GMT+1。

如果您阅读文档,您会发现getTime()

返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。

所以 100 毫秒的意思January 1, 1970, 00:00:00.100 GMTJanuary 1, 1970, 01:00:00.100 GMT+1

您可以简单地设置您希望时间转换为的时区:

timeFormat.setTimeZone(TimeZone.getTimeZone("GMT"));

并且您需要 24 小时格式:HH:mm:ss.SSS,否则它将显示 12 而不是 00 小时。

编辑:正如jarnbjo所说:您正在尝试将日期格式化程序应用于时间间隔,这显然不会像您预期的那样工作。Java API 中没有这样的时间间隔格式化程序。你必须自己写。

于 2013-08-07T14:39:15.970 回答