【问题标题】:Computing the difference of two dates计算两个日期的差
【发布时间】:2014-08-14 11:31:35
【问题描述】:

我写了一个小程序来打印两个Date对象之间的差异:

public static void main(final String[] args) throws Exception {
    final DateFormat df = new SimpleDateFormat("HH:mm:ss.SSSSSS");
    final Date start = Calendar.getInstance().getTime();

    Thread.sleep(1000);

    final Date end = Calendar.getInstance().getTime();
    final long startMilliseconds = start.getTime();
    final long endMilliseconds = end.getTime();
    final long runtimeMilliseconds = endMilliseconds - startMilliseconds;
    final Date runtime = new Date(runtimeMilliseconds);

    System.out.print("Start  : " + df.format(start));
    System.out.println("\t Milliseconds: " + startMilliseconds);
    System.out.print("End    : " + df.format(end));
    System.out.println("\t Milliseconds: " + endMilliseconds);
    System.out.print("Runtime: " + df.format(runtime));
    System.out.println("\t Milliseconds: " + runtimeMilliseconds);
    System.out.println();
    System.out.println("Milliseconds from new Date object: " + runtime.getTime());
}

它给出以下输出:

Start  : 13:24:54.000871     Milliseconds: 1408015494871
End    : 13:24:55.000871     Milliseconds: 1408015495871
Runtime: 01:00:01.000000     Milliseconds: 1000

Milliseconds from new Date object: 1000

毫秒之间的差异是正确的,但是新创建的Date 对象增加了一个小时。 runtime 对象的预期输出为:00:00:01.000000。我认为这是因为我的时区 (GMT+1)。如何计算两个 Date 对象之间的差异并获得一个新的 Date 对象,其中不包括额外的小时?我想使用 Joda-Time 或其他库。

【问题讨论】:

  • 为什么Calendar.getInstance().getTime() 而不仅仅是System.currentTimeMillis()
  • 实际上并不清楚你在问什么:你已经编写了你想要的代码。
  • 只是一个测试程序。在我的真实程序中,我也需要 Date 对象。预期输出为00:00:01.000000,但实际输出为01:00:01.000000
  • 您正试图在Date 对象中存储一定量的时间(例如,1000 毫秒)。但是Date 对象不适合存储数量的时间。 Date 对象是一个时间戳,它总是有一个日期和时间。如果您将“1000”存储在 Date 对象中,那么您将获得设置为 01-01-1970 00:00:01 GMT 的时间戳。

标签: java date timezone


【解决方案1】:

要达到您想要的行为,您需要设置正确的时区,即GMT-00,因为使用您使用的构造函数创建的Date 对象将是自 1970 年 1 月 1 日 00 日以来的 毫秒:格林威治标准时间 00:00.

为此,只需设置DateFormat df:

df.setTimeZone(TimeZone.getTimeZone("GMT-00"));

在其实例化之后(然后StartEnd 日期也将与新时区一起显示)或在新Date runtime 打印之前(然后StartEnd 日期将显示在您当地的时区);之后,如果您想保留它以供将来使用,您可以重置原始本地时区。

输出将是您想要的这种类型:

Start  : 11:51:37.000287     Milliseconds: 1408017097287
End    : 11:51:38.000287     Milliseconds: 1408017098287
Runtime: 00:00:01.000000     Milliseconds: 1000

Milliseconds from new Date object: 1000

【讨论】:

  • 这忽略了根本问题,为什么要在 Date 对象中存储时间增量?
  • 你是对的,但我遵循了他所描述的代码的期望行为。
  • 虽然它给出了正确的输出,但如果同行或教师要审查代码,他们可能会想,“这真的是一个日期吗?”。
  • 另外一点是,如果时间增量超过24小时怎么办?那么这将是完全错误的。
  • 我既不是讲师也不是审稿人 ;) 而且我认为他的代码既不是学校作业也不是大型商业项目,因为他说这只是一个测试程序 :) 但是不管怎样,从理论上讲,你是对的。
【解决方案2】:

您的问题是您将持续时间视为Date。 1000 毫秒作为 Date 没有任何意义,因为 Date 自纪元以来就是 MS。不要尝试将其转换为Date,只需将其用作long

如果您使用的是 Java 8,请考虑使用 Duration。或者你可以使用 JodaTime。如果您只需要long,似乎这些可能有点矫枉过正。

根据您的问题,格式化它取决于您是否使用 Java 8。如果是,请使用其Duration。否则,使用 JodaTime & Duration、Period 和 PeriodFormatter。这在帖子中有所描述:

joda-time-period-to-string

我承认这是一个比其他人建议的设置时区更复杂的解决方案。但是,我建议这是一个更正确的解决方案。如果时间增量超过一天,则尤其如此。在那种情况下,这个解决方案将是完全错误的。

如果时间增量为 24 小时 1 秒,您的 HH:mm:ss.SSSSS 格式将显示 00:00:01.00000 而不是 '24:00:01.0000`

【讨论】:

  • 如何以HH:mm:ss.SSSSSS 格式打印时间增量?
  • 我明白你在说什么。感谢您的澄清。现在我将坚持使用时区解决方案,因为差异不会超过几分钟。但我肯定会看看 Joda-Time,因为我还在使用 java 7。
  • 一定要看看。它是一个比 Java 内置的更好的日期库。这就是他们在 Java 8 中添加更新的原因。既然你知道你不到 24 小时,你应该很好。干杯。
【解决方案3】:

实际上,您正在使用 Date 类,更具体地说,SimpleDateFormat 类以错误的方式使用。

您在问题中写的一切正确:runtime 对象中的额外小时是由于您的时区 (GMT+1)。

runtime 对象的内部表示是time = 1000,即00:00:01 of January 1, 1970 GMT

如果你想准确地看到这个日期,你应该以适当的方式修改你的格式化程序:

    final DateFormat dfGmt0 = new SimpleDateFormat("HH:mm:ss.SSSSSS");
    dfGmt0.setTimeZone(TimeZone.getTimeZone("GMT+0"));

【讨论】:

    【解决方案4】:

    你得到这个 Runtime: 01:00:01.000000 Milliseconds: 1000 因为你当前的时区是 UTC+01:00 。为 Dateformatter 设置时区 GMT-00。

    【讨论】:

      猜你喜欢
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 2013-02-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-20
      相关资源
      最近更新 更多