【问题标题】:Calculating difference in dates in Java计算Java中的日期差异
【发布时间】:2010-10-01 23:44:47
【问题描述】:

我觉得很有趣的是,Java(或 java.util 库)没有内置函数来计算日期差异。我想从另一个日期中减去一个日期以获得它们之间的经过时间。做这个的最好方式是什么?

我知道简单的方法是以毫秒为单位的时间差,然后将其转换为天。但是,我想知道这是否适用于所有情况(夏令时等)。

【问题讨论】:

  • 查看xmission.com/~goodhill/dates/deltaDates.html了解一些背景信息。
  • 这篇文章不错。谢谢!
  • @Anirudh 在 StackOverflow 中搜索“joda”和“span”、“Interval”、“Duration”、“Period”等术语。你会发现很多讨论的例子。

标签: java date datetime date-arithmetic


【解决方案1】:

如果您查看开源代码,Java 并没有丢失太多:试试Joda-Time

【讨论】:

  • 关于 Java 日期的问题 ==> 回答提到了 Joda!
  • 是的,当一种语言有 2 个缺陷日期/时间类时,它就是这样工作的。
  • 我查看了 Joda - 不幸的是,我不允许使用非标准库:(
  • 我认为 Joda 现在非常标准:-)
  • 确实,Joda-Time 的后代(java.time package)从昨天开始成为 Java 的官方部分,与 Java 8 的发布捆绑在一起。
【解决方案2】:

我知道简单的方法是采取 以毫秒为单位的时间差 然后将其转换为天数。 但是,我想知道这是否 适用于所有情况(白天 保存等)。

如果您的时间来自 UTC 日期,或者它们只是在同一系统上测量的两次 System.getCurrentTimeMillis() 调用之间的差异,您将获得有效的毫秒数作为差异,与任何时区问题无关. (这就是为什么一切都应该使用 UTC 作为存储格式的原因——从 UTC-> 本地时间开始要容易得多;如果你尝试另一种方式,那么你需要将本地时区与本地时间一起存储——或尝试推断它,gack!)

至于将其转换为天数,您应该只能除以 86400000... 需要注意的是每隔一年左右偶尔会出现 leap second

【讨论】:

    【解决方案3】:

    使用 Joda-Time 或 Java 8 中的新 java.time 包。

    两个框架都使用 Half-Open 方法,其中开始是inclusive,而结束是exclusive。有时记为[)。这通常是定义时间跨度的最佳方法。

    java.time

    Java 8 及更高版本中内置的 java.time 框架有一个 Period 类,用于将时间跨度表示为年数、月数和天数。但是这个类仅限于整天,没有小时、分钟和秒的表示。

    请注意,我们指定了一个时区,这对于确定日期至关重要。例如,Paris 的新一天比Montréal 早。

    ZoneId zoneId = ZoneId.of( "America/Montreal" );
    LocalDate now = LocalDate.now( zoneId );
    LocalDate then = LocalDate.of( 2001, 1, 1 );
    Period period = Period.between( then, now );
    

    然后:2001-01-01。现在:2015-09-07。期间:P14Y8M6D。天数:5362

    一整天,Daylight Saving Time (DST) 是无关紧要的。

    如果您想要计算总天数,请使用包含一些计算方法的 ChronoUnit 枚举。请注意,计算返回一个 long。

    long days = ChronoUnit.DAYS.between( then, now );  // "5362" seen above.
    

    I have asked 关于在 java.time 中做一个完整的时间段,包括小时、分钟、秒。从 Java 8 开始不可能。使用 Meno Hochschild 的捆绑库 was suggested 的一个令人惊讶的解决方法是:使用在 javax.xml.datatype package 中找到的 Duration 类。

    乔达时间

    这是 Joda-Time 2.3 中的一些示例代码。

    DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
    DateTime start = new DateTime( 2014, 1, 2, 3, 4, 5, timeZone );
    DateTime stop = new DateTime( 2014, 5, 2, 3, 4, 5, timeZone );
    Period period = new Period( start, stop );
    

    调用toString 会得到一个由ISO 8601 标准定义的字符串表示形式PnYnMnDTnHnMnS

    【讨论】:

      【解决方案4】:

      使用date4j 库:

      int numDaysBetween = oneDate.numDaysFrom(anotherDate);
      

      【讨论】:

        【解决方案5】:

        有一个简单的方法来实现它。我们可以使用带有循环的 Calendar.add 方法。 比如下图,

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        
        Date beginDate = dateFormat.parse("2013-11-29");
        Date endDate = dateFormat.parse("2013-12-4");
        
        Calendar beginCalendar = Calendar.getInstance();
        beginCalendar.setTime(beginDate);
        
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endDate);
        

        beginDate和endDate之间的负天数,代码如下,

        int minusDays = 0;
        while (true) {
          minusDays++;
        
          // Day increasing by 1
          beginCalendar.add(Calendar.DAY_OF_MONTH, 1);
        
          if (dateFormat.format(beginCalendar.getTime()).
                    equals(dateFormat.format(endCalendar).getTime())) {
            break;
          }
        }
        System.out.println("The substractation between two days is " + (minusDays + 1));
        

        玩得开心! @.@

        【讨论】:

        • 我以前用过这个方法。但是,它的运行时间是 O(N),其中 N 是 beginDate 和 endDate 之间的天数。我怀疑使用 JodaTime 会产生更好的结果。
        • 是的,你是对的。但我认为 O(n) 对于某些项目是可以接受的。因为我不想导入一些库。仍然感谢您的建议。
        【解决方案6】:

        我不同意 Java 没有计算日期之间差异的机制的说法。

        Java 是为全球使用而设计的。它被设计成没有日期的概念,只有“以毫秒为单位的时间”的概念。在特定约定下,对特定地点的时间和日期这样的世界时间的任何解释都只是一种投影或一种看法。

        日历类用于将这种绝对时间转换为日期。如果确实需要,您还可以添加或减去日期组件。在两次之间提供组件术语差异的唯一方法是日历生成和特定。因此,您可能会争辩说标准库不包含足够智能的公历,我同意它还有一些不足之处。

        话虽如此,这种功能有很多实现,我看到其他人提供了示例。

        【讨论】:

        • 我原则上同意你的看法。我声称 Java 没有此功能是基于这样一个事实,即其他语言(Ruby、Python 等)在标准 Date 类中具有非常简单(且有效)的加减日期实现。
        【解决方案7】:

        Java 的日期实现很差。如果你觉得Joda-Time 太复杂,试试我对开源的一点贡献: http://calendardate.sourceforge.net/javadoc/index.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-25
          • 2015-01-13
          • 2018-04-24
          • 2012-04-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多