【问题标题】:Java, Calculate the number of days between two dates [duplicate]Java,计算两个日期之间的天数[重复]
【发布时间】:2011-10-29 12:07:14
【问题描述】:

可能重复:
Calculating the Difference Between Two Java Date Instances

在 Java 中,我想计算两个日期之间的天数。

在我的数据库中,它们存储为 DATE 数据类型,但在我的代码中,它们是字符串。

我想计算这两个字符串之间的天数。

【问题讨论】:

    标签: java string date


    【解决方案1】:

    Java 8 及更高版本:ChronoUnit.between

    使用ChronoUnit 的实例来计算不同单位(天、月、秒)的时间量。

    例如:

    ChronoUnit.DAYS.between(startDate,endDate)
    

    【讨论】:

    • 说我需要使用 Temporal 而不是 Date 有什么想法吗?
    • Instant now = date1.toInstant();
    • 最近发现这个方法有个问题:startDateendDate之间有冬夏时间的变化。由于他们俩都在00:00:00 度过了一段时光,因此endDateInstant 的转换在一小时前产生了结果,因此中间的天数比实际结果少了一天。
    【解决方案2】:

    我计算天数差异的最佳解决方案(到目前为止):

    //  This assumes that you already have two Date objects: startDate, endDate
    //  Also, that you want to ignore any time portions
    
    Calendar startCale=new GregorianCalendar();
    Calendar endCal=new GregorianCalendar();
    
    startCal.setTime(startDate);
    endCal.setTime(endDate);
    
    endCal.add(Calendar.YEAR,-startCal.get(Calendar.YEAR));
    endCal.add(Calendar.MONTH,-startCal.get(Calendar.MONTH));
    endCal.add(Calendar.DATE,-startCal.get(Calendar.DATE));
    
    int daysDifference=endCal.get(Calendar.DAY_OF_YEAR);
    

    但是,请注意,这假设相差不到一年!

    【讨论】:

      【解决方案3】:

      我知道这个帖子已经有两年了,我在这里仍然没有看到正确的答案。

      除非您想使用 Joda 或 Java 8,并且如果您需要减去受夏令时影响的日期。

      所以我编写了自己的解决方案。重要的方面是它只有在你真的只关心日期时才有效,因为有必要丢弃时间信息,所以如果你想要25.06.2014 - 01.01.2010 = 1636 之类的东西,无论夏令时如何,这都应该有效:

      private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy");
      
      public static long getDayCount(String start, String end) {
        long diff = -1;
        try {
          Date dateStart = simpleDateFormat.parse(start);
          Date dateEnd = simpleDateFormat.parse(end);
      
          //time is always 00:00:00, so rounding should help to ignore the missing hour when going from winter to summer time, as well as the extra hour in the other direction
          diff = Math.round((dateEnd.getTime() - dateStart.getTime()) / (double) 86400000);
        } catch (Exception e) {
          //handle the exception according to your own situation
        }
        return diff;
      }
      

      由于时间始终是00:00:00,使用 double 然后Math.round() 应该有助于忽略从冬季到夏季时缺少的 3600000 毫秒(1 小时),以及从夏季到夏季时的额外小时冬天。

      这是我用来证明它的一个小型 JUnit4 测试:

      @Test
      public void testGetDayCount() {
        String startDateStr = "01.01.2010";
        GregorianCalendar gc = new GregorianCalendar(locale);
        try {
          gc.setTime(simpleDateFormat.parse(startDateStr));
        } catch (Exception e) {
        }
      
        for (long i = 0; i < 10000; i++) {
          String dateStr = simpleDateFormat.format(gc.getTime());
          long dayCount = getDayCount(startDateStr, dateStr);
          assertEquals("dayCount must be equal to the loop index i: ", i, dayCount);
          gc.add(GregorianCalendar.DAY_OF_YEAR, 1);
        }
      }
      

      ...或者如果你想看看它在“生活”中做了什么,只需将断言替换为:

      System.out.println("i: " + i + " | " + dayCount + " - getDayCount(" + startDateStr + ", " + dateStr + ")");
      

      ...这就是输出的样子:

        i: 0 | 0  - getDayCount(01.01.2010, 01.01.2010)
        i: 1 | 1  - getDayCount(01.01.2010, 02.01.2010)
        i: 2 | 2  - getDayCount(01.01.2010, 03.01.2010)
        i: 3 | 3  - getDayCount(01.01.2010, 04.01.2010)
        ...
        i: 1636 | 1636  - getDayCount(01.01.2010, 25.06.2014)
        ...
        i: 9997 | 9997  - getDayCount(01.01.2010, 16.05.2037)
        i: 9998 | 9998  - getDayCount(01.01.2010, 17.05.2037)
        i: 9999 | 9999  - getDayCount(01.01.2010, 18.05.2037)
      

      【讨论】:

        【解决方案4】:

        这个功能对我有好处:

        public static int getDaysCount(Date begin, Date end) {
            Calendar start = org.apache.commons.lang.time.DateUtils.toCalendar(begin);
            start.set(Calendar.MILLISECOND, 0);
            start.set(Calendar.SECOND, 0);
            start.set(Calendar.MINUTE, 0);
            start.set(Calendar.HOUR_OF_DAY, 0);
        
            Calendar finish = org.apache.commons.lang.time.DateUtils.toCalendar(end);
            finish.set(Calendar.MILLISECOND, 999);
            finish.set(Calendar.SECOND, 59);
            finish.set(Calendar.MINUTE, 59);
            finish.set(Calendar.HOUR_OF_DAY, 23);
        
            long delta = finish.getTimeInMillis() - start.getTimeInMillis();
            return (int) Math.ceil(delta / (1000.0 * 60 * 60 * 24));
        }
        

        【讨论】:

          【解决方案5】:

          这是一个可以帮助你的小程序:

          import java.util.*;
          
          public class DateDifference {
              public static void main(String args[]){
                  DateDifference difference = new DateDifference();
              }
          
              DateDifference() {
                  Calendar cal1 = new GregorianCalendar();
                  Calendar cal2 = new GregorianCalendar();
          
                  cal1.set(2010, 12, 1); 
                  cal2.set(2011, 9, 31);
                  System.out.println("Days= "+daysBetween(cal1.getTime(),cal2.getTime()));
              }
          
              public int daysBetween(Date d1, Date d2) {
                  return (int)( (d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24));
              }
          }
          

          【讨论】:

          • 我要编辑的一件事是:``` public long daysBetween(Date d1, Date d2){ return ( (d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24)); }```
          【解决方案6】:

          我真的是 Java 的新手,所以我确信有更好的方法来做我提议的事情。

          我也有同样的需求,我使用两个日期的 DAYOFYEAR 之间的差异来做到这一点。 这似乎是一种更简单的方法......

          我无法真正从性能和稳定性方面评估此解决方案,但我认为还可以。

          这里:

          公共静态 void main(String[] args) 抛出 ParseException { //制作这部分代码只是为了创建我将使用的变量。 //我在巴西,这里的日期格式是 DD/MM/YYYY,但对你们来说不是问题。 //无论如何它都适用于您的格式。 字符串 s1 = "18/09/2014"; 字符串 s2 = "01/01/2014"; DateFormat f = DateFormat.getDateInstance(); 日期 date1 = f.parse(s1); 日期 date2 = f.parse(s2); //这是我们获取两个日期之间的天数的部分。 日历 day1 = Calendar.getInstance(); 日历 day2 = Calendar.getInstance(); day1.setTime(date1); day2.setTime(date2); int daysBetween = day1.get(Calendar.DAY_OF_YEAR) - day2.get(Calendar.DAY_OF_YEAR); //一些代码只是为了显示结果... f = DateFormat.getDateInstance(DateFormat.MEDIUM); System.out.println("" + f.format(day1.getTime()) + " 和 " + f.format(day2.getTime()) + ".") 之间有 " + daysBetween + " 天; }

          在这种情况下,输出将是(记住我使用的是日期格式 DD/MM/YYYY):

          从 18/09/2014 到 01/01/2014 之间有 260 天。

          【讨论】:

          • 这不起作用,因为它只告诉您一年中的天数之间的差异,而不是总运行天数。
          【解决方案7】:

          首先,您应该在必要时将它们作为字符串处理。大多数情况下,您应该使用实际描述您正在使用的数据的数据类型来使用它们。

          我建议您使用Joda Time,它是一个比Date/Calendar 更好的API。在这种情况下,听起来您应该使用 LocalDate 类型。然后你可以使用:

          int days = Days.daysBetween(date1, date2).getDays();
          

          【讨论】:

          • 似乎这个方法是独占的而不是包容的,所以可能想在结果中加 1(或者在 date2 中加 25(而不是 24)小时)到使其具有包容性。
          • @AlaaM.:好吧,如果你想让它具有包容性。如果有人问我 12 月 24 日到 12 月 25 日之间的天数,我会说 1,而不是 2...(而且 OP 似乎很高兴。)
          • 是的,这就是我说可能想要的原因。就我而言,我需要显示“到期前的剩余天数”。所以在我看来这个案例应该是包容性的
          【解决方案8】:
          // http://en.wikipedia.org/wiki/Julian_day
          public static int julianDay(int year, int month, int day) {
            int a = (14 - month) / 12;
            int y = year + 4800 - a;
            int m = month + 12 * a - 3;
            int jdn = day + (153 * m + 2)/5 + 365*y + y/4 - y/100 + y/400 - 32045;
            return jdn;
          }
          
          public static int diff(int y1, int m1, int d1, int y2, int m2, int d2) {
            return julianDay(y1, m1, d1) - julianDay(y2, m2, d2);
          }
          

          【讨论】:

            【解决方案9】:

            如果您厌倦了使用 java,您可以将其作为查询的一部分发送到 db2:

            select date1, date2, days(date1) - days(date2) from table
            

            将返回 date1、date2 以及两者之间的天数差。

            【讨论】:

            • 由于最初的问题是关于 JAVA 的问题,所以留在话题上可能会很好。
            【解决方案10】:

            试试这个代码

                 Calendar cal1 = new GregorianCalendar();
                 Calendar cal2 = new GregorianCalendar();
            
                 SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");
            
                 Date date = sdf.parse("your first date");
                 cal1.setTime(date)
                 date = sdf.parse("your second date");
                 cal2.setTime(date);
            
                //cal1.set(2008, 8, 1); 
                 //cal2.set(2008, 9, 31);
                 System.out.println("Days= "+daysBetween(cal1.getTime(),cal2.getTime()));
            

            这个函数

                 public int daysBetween(Date d1, Date d2){
                         return (int)( (d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24));
                 }
            

            【讨论】:

            • 这个方法将如何处理夏令时变化?
            • 这个公式不错,但是会少1天。例如,d1 = 2016 年 1 月 2 日,d2 = 2016 年 1 月 1 日,它会给您 1 天而不是 2 天。
            • @stanicmail 但是在 2016 年 1 月 1 日到 2 月 2 日之间只有一天!当然,除非您在 d0 = 2015 年 12 月 31 日喝得太多。 ;-)
            • 仅供参考,这些可怕的日期时间类在几年前已被现代 java.time 类所取代。所以这个答案现在已经过时了。请参阅other Answer 了解现代解决方案。
            猜你喜欢
            • 2012-12-07
            • 2019-02-10
            • 2013-12-08
            • 2014-07-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多