【问题标题】:Java - Time difference in minutesJava - 以分钟为单位的时差
【发布时间】:2016-10-27 13:00:19
【问题描述】:

我在以分钟为单位计算时差时遇到了这个问题。 它可以很好地处理示例,例如计算两者之间的差异 2045 和 2300。

但是当我想计算例如之间的差异时 2330(今天)和 0245(明天)我得到一个错误的答案。 代码如下:

    // This example works
    String dateStart = "2045";
    String dateStop = "2300";

    // This example doesnt work
    //String dateStart = "2330";
    //String dateStop = "0245";

    // Custom date format
    SimpleDateFormat format = new SimpleDateFormat("HHmm");  

    Date d1 = null;
    Date d2 = null;
    try {
        d1 = format.parse(dateStart);
        d2 = format.parse(dateStop);
    } catch (Exception e) {
        e.printStackTrace();
    }    

    long diff = d2.getTime() - d1.getTime();
    long minutes = TimeUnit.MILLISECONDS.toMinutes(diff);                      
    System.out.println("Time in minutes: " + minutes + " minutes.");

提前致谢

【问题讨论】:

  • d2需要加1天。
  • 想想你的程序如何知道时间不是从当天开始的。
  • @Semith 你是如何解决你的问题的?我的回答有帮助吗?正确答案是什么?谢谢。

标签: java


【解决方案1】:

考虑使用 Java 8 中引入的 java.time.* 包中的 LocalDate、LocalDateTime、LocalTime ZonedDateTime 类。它们使用起来非常方便,因为它们可以解决各种极端情况(例如,测量不同时间的分钟数区,或在秋季和春季时间变化期间)。

计算时差时你需要知道的是:

  • LocalTime 仅包含时间
  • LocalDate 仅包含日期(无时间)
  • LocalDateTime 包含两者(日期 + 时间)。
  • ZonedDateTime 包含日期 + 时间 + 时区

这意味着当您比较时,时间之间的差异会有所不同:

  • LocalTime 您只能区分时间,因此 20:45 和 23:30 给出 2:45 的差异
  • LocalDate 您无法计算任何时间差异(不包含时间)
  • LocalDateTime 您可以指定日期和时间,例如:20:45 on 1Jan 和 23:30 on 3Jan。时差为 2:45 和 2 天的时差,即 50:45。
  • ZonedDateTime - 与 LocalDateTime 相同,另外您还考虑了 DayLightSavings,因此如果一夜之间更改时钟 - 它会得到反映。

这是 LocalDateTime 的 sn-p:

    LocalDateTime today2045    = LocalDateTime.of(
            LocalDate.now(),
            LocalTime.parse("20:45"));
    LocalDateTime tomorrow0230 = LocalDateTime.of(
            LocalDate.now().plusDays(1),
            LocalTime.parse("02:30"));

    System.out.println("Difference [minutes]: " + 
            Duration.between(today2045, tomorrow0230).toMinutes());

ZonedDateTime 考虑到春秋时钟变化:

    ZonedDateTime today2045    = ZonedDateTime.of(
            LocalDate.now(),
            LocalTime.parse("20:45"),
            ZoneId.systemDefault());
    ZonedDateTime tomorrow0230 = ZonedDateTime.of(
            LocalDate.now().plusDays(1),
            LocalTime.parse("02:30"),
            ZoneId.systemDefault());

    System.out.println("Difference [minutes]: " + 
            Duration.between(today2045, tomorrow0230).toMinutes());

关于构造函数的一些信息可以在Oracle's tutorial here找到。

【讨论】:

  • 为什么要投反对票?这回答了问题并且符合最新建议(???)。
  • 可能是因为在这个问题的两个答案中发布了相同的材料?
  • @Basil Bourqe:不。这个首先得到了反对票。我想我正在编辑它,当我完成时 - 我投了反对票。
  • (A) 当您清理并合并为一个答案时,我会很乐意投票。 (B) 我建议使用名称“java.time”而不是“Java 8”,因为该名称不会老化。 (C) 代码 sn-ps 可能比带有人为设计的 for 循环的完整类更容易阅读。作为补充,您可以将完整的代码放入 IdeOne.com 等在线工具中,如果您愿意,可以从您的答案中链接到它。
  • 感谢您的建议。尤其是关于 sn-ps 的。将牢记这一点,并在今天晚些时候完成这些更改。
【解决方案2】:

这不起作用,因为当您创建一个仅包含时间的新日期时,它会假设这一天是“今天”。

你可以做的是:

// This example works
String dateStart = "2045";
String dateStop = "2300";

// This example doesnt work
//String dateStart = "2330";
//String dateStop = "0245";

// Custom date format
SimpleDateFormat format = new SimpleDateFormat("HHmm");  

Date d1 = null;
Date d2 = null;
try {
    d1 = format.parse(dateStart);
    d2 = format.parse(dateStop);
} catch (Exception e) {
    e.printStackTrace();
}

// MY ADDITION TO YOUR CODE STARTS HERE
if(d2.before(d1)){
    Calendar c = Calendar.getInstance(); 
    c.setTime(d2); 
    c.add(Calendar.DATE, 1);
    d2 = c.getTime();
}
// ENDS HERE

long diff = d2.getTime() - d1.getTime();
long minutes = TimeUnit.MILLISECONDS.toMinutes(diff);                      
System.out.println("Time in minutes: " + minutes + " minutes.");

但您应该考虑使用 Java 8 新的日期/时间功能,或 Joda Time。

【讨论】:

  • Joda 时间(或 Java 8 函数)是解决此问题的唯一可靠方法
  • 虽然 Java 8 功能肯定是一个改进,但我认为答案完全可靠,我挑战你,@Stormcloud,指出它不是什么方式(我不知道乔达时间足以有一个合格的意见)。
  • 这行得通,非常感谢。你能把我链接到新的 Java 8 函数吗?对 Java 还是有点陌生​​,不了解新功能
【解决方案3】:

你可以添加if语句来检查这是不是今天,如果不是你可以添加一天,因为你是在比较时间,如果你添加全天不会有问题

    if(d2.before(d1)){
        d2.setTime(d2.getTime()+86400000);
    }

试试看

【讨论】:

  • 这比我原来的回答方式要好得多。我已经用你的代码更新了我的答案。谢谢!
  • 86400000 假设所有的日子正好有 24 小时。夏令时失败
  • 它没有,因为它总是将 24 小时添加到 1970 年 1 月 1 日
【解决方案4】:

这是一个已解决的问题。如果您查看 Joda Time 库,您会发现您可能想要的所有时间和日期操作函数:

你的情况是这样的:

DateTime first = new DateTime(larger-time);
DateTime second = new DateTime(smaller-time);
DateTime difference = first.minusMillis(second.getMillis())

Joda 将应对所有奇怪的边缘条件,例如在日/月/年之间滚动、月长、闰年、夏令时、时区...

【讨论】:

  • 哇!大量反对使用受人尊敬的图书馆的投票。任何身体护理都可以解释原因
  • 您回复的初始版本没有可用的答案,只是建议去图书馆看看。就是说,java.time 基本相同,不需要依赖,为什么还要依赖第三方库?
  • 啊,是的。我整理了一个快速答案,然后对其进行了编辑以包含一个示例。当我完成时,我投了 3 票反对票——不到 3 分钟!更糟糕的是,赞成的答案并非在所有情况下都有效。你说得对,java.time 是一样的,但它只是 Java 8。
  • 一些事实性的更正...... Joda-Time 不与 java.time 相同。它们共享一些基本概念,共享一些类/方法名称,共享同一个领导者(Stephen Colbourne),但彼此不同。 Joda-Time 启发了 java.time,但现在 Joda-Time 处于维护模式,团队建议迁移到 java.time 类。是的,java.time 内置在 Java SE 8 中,在 Java SE 9 中添加了一些小功能和修复。但大部分功能在 ThreeTen-Backport 项目中向后移植到 Java 6 和 7 ,并在 ThreeTenABP 中进一步适用于 Android。
  • 我将问题理解为找出例如"2330"(今天)和"0245"(明天)之间的分钟差异。我看不出你已经回答了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多