Java中两个日期之间的天数差异?

Ven*_*kat 81 java datediff jodatime

我需要找到两个日期之间的天数:一个来自报告,一个是当前日期.我的片段:

  int age=calculateDifference(agingDate, today);
Run Code Online (Sandbox Code Playgroud)

calculateDifference是一个私有方法,agingDate并且todayDate对象,仅供您澄清.我已经关注了Java论坛中的两篇文章,即Thread 1/Thread 2.

它在独立程序中运行良好,但是当我将其包含在我的逻辑中以从报告中读取时,我会得到一个不寻常的值差异.

为什么会发生这种情况?我该如何解决?

编辑:

与实际天数相比,我获得的天数更多.

public static int calculateDifference(Date a, Date b)
{
    int tempDifference = 0;
    int difference = 0;
    Calendar earlier = Calendar.getInstance();
    Calendar later = Calendar.getInstance();

    if (a.compareTo(b) < 0)
    {
        earlier.setTime(a);
        later.setTime(b);
    }
    else
    {
        earlier.setTime(b);
        later.setTime(a);
    }

    while (earlier.get(Calendar.YEAR) != later.get(Calendar.YEAR))
    {
        tempDifference = 365 * (later.get(Calendar.YEAR) - earlier.get(Calendar.YEAR));
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    if (earlier.get(Calendar.DAY_OF_YEAR) != later.get(Calendar.DAY_OF_YEAR))
    {
        tempDifference = later.get(Calendar.DAY_OF_YEAR) - earlier.get(Calendar.DAY_OF_YEAR);
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    return difference;
}
Run Code Online (Sandbox Code Playgroud)

注意 :

不幸的是,没有一个答案帮助我解决了这个问题.我在Joda-time库的帮助下完成了这个问题.

Ada*_*deg 149

我建议你使用优秀的Joda Time库而不是有缺陷的java.util.Date和朋友.你可以简单地写

import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.Days;

Date past = new Date(110, 5, 20); // June 20th, 2010
Date today = new Date(110, 6, 24); // July 24th 
int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays(); // => 34
Run Code Online (Sandbox Code Playgroud)

  • http://joda-time.sourceforge.net/faq.html#datediff - 我即将提出同样的建议. (3认同)
  • jodaInstance = new DateTime(jdkDate); 关于joda time和java.util.Date以及朋友之间的转换,请参阅http://joda-time.sourceforge.net/userguide.html#JDK_Interoperability (2认同)
  • @ven coder - 我想你可以将它作为一个关于使用joda时间的单独问题发布.您还可以提供一个代码片段,该代码片段看似错误的结果. (2认同)
  • @ven编码器 - 我更新了示例代码,它适用于我.我看到这个问题得到了回答 在此处或单独的问题中显示不适合您的代码. (2认同)

小智 48

I might be too late to join the game but what the heck huh? :)

Do you think this is a threading issue? How are you using the output of this method for example? OR

Can we change your code to do something as simple as:

Calendar calendar1 = Calendar.getInstance();
    Calendar calendar2 = Calendar.getInstance();
    calendar1.set(<your earlier date>);
    calendar2.set(<your current date>);
    long milliseconds1 = calendar1.getTimeInMillis();
    long milliseconds2 = calendar2.getTimeInMillis();
    long diff = milliseconds2 - milliseconds1;
    long diffSeconds = diff / 1000;
    long diffMinutes = diff / (60 * 1000);
    long diffHours = diff / (60 * 60 * 1000);
    long diffDays = diff / (24 * 60 * 60 * 1000);
    System.out.println("\nThe Date Different Example");
    System.out.println("Time in milliseconds: " + diff
 + " milliseconds.");
    System.out.println("Time in seconds: " + diffSeconds
 + " seconds.");
    System.out.println("Time in minutes: " + diffMinutes 
+ " minutes.");
    System.out.println("Time in hours: " + diffHours 
+ " hours.");
    System.out.println("Time in days: " + diffDays 
+ " days.");
  }
Run Code Online (Sandbox Code Playgroud)

  • 此代码不关注夏令时,因此天数差异的结果可能不正确. (18认同)
  • 仅当您处于使用夏令时的时区(您当地的时区设置)时才会出现此错误,例如中欧时间,柏林,巴黎或阿姆斯​​特丹.夏令时的开始和结束日期没有24小时,例如2014年3月30日只有23小时,而2014年10月26日则有25小时.如果较早的日期是在3月30日2:00之前,而较晚的日期是在3月30日3:00之后,则计算失败. (4认同)

小智 23

diff /(24*etc)不考虑Timezone,因此如果您的默认时区中有DST,它可以关闭计算.

这个链接有一个很好的实现.

如果链接断开,以下是上述链接的来源:

/** Using Calendar - THE CORRECT WAY**/  
public static long daysBetween(Calendar startDate, Calendar endDate) {  
  //assert: startDate must be before endDate  
  Calendar date = (Calendar) startDate.clone();  
  long daysBetween = 0;  
  while (date.before(endDate)) {  
    date.add(Calendar.DAY_OF_MONTH, 1);  
    daysBetween++;  
  }  
  return daysBetween;  
}  
Run Code Online (Sandbox Code Playgroud)

/** Using Calendar - THE CORRECT (& Faster) WAY**/  
public static long daysBetween(final Calendar startDate, final Calendar endDate)
{
  //assert: startDate must be before endDate  
  int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;  
  long endInstant = endDate.getTimeInMillis();  
  int presumedDays = 
    (int) ((endInstant - startDate.getTimeInMillis()) / MILLIS_IN_DAY);  
  Calendar cursor = (Calendar) startDate.clone();  
  cursor.add(Calendar.DAY_OF_YEAR, presumedDays);  
  long instant = cursor.getTimeInMillis();  
  if (instant == endInstant)  
    return presumedDays;

  final int step = instant < endInstant ? 1 : -1;  
  do {  
    cursor.add(Calendar.DAY_OF_MONTH, step);  
    presumedDays += step;  
  } while (cursor.getTimeInMillis() != endInstant);  
  return presumedDays;  
}
Run Code Online (Sandbox Code Playgroud)

  • 第二种方法是错误的,最后的`while`应该是.`while(cursor.getTimeInMillis()<= endInstant); `否则,如果不到一天,你会得到一个无限循环. (4认同)

Vit*_*nko 16

java.time

在Java 8及更高版本中,使用java.time框架(Tutorial).

Duration

所述Duration类表示一时间跨度为秒数加的分数秒.它可以计算天,小时,分钟和秒.

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println(duration.toDays());
Run Code Online (Sandbox Code Playgroud)

ChronoUnit

如果您只需要天数,或者您可以使用枚举.请注意,计算方法返回的是而不是.ChronoUnit longint

long days = ChronoUnit.DAYS.between( then, now );
Run Code Online (Sandbox Code Playgroud)

  • 啊!!Java 8 ... :-) (4认同)

Pet*_*rey 13

这取决于你定义的差异.要比较午夜的两个日期,你可以做到.

long day1 = ...; // in milliseconds.
long day2 = ...; // in milliseconds.
long days = (day2 - day1) / 86400000;
Run Code Online (Sandbox Code Playgroud)

  • 此代码不注意夏令时,因此结果可能不正确. (9认同)
  • @Muhd是的,你是对的.第三行必须是:long days = Math.round((day2 - day1)/ 86400000D); 除数是双重值是非常重要的. (3认同)
  • 抱歉.今天早上我忘记将我的一年级数学模块插入我的大脑.我在想减去负数会导致计算失败.我们应该能够进行评论. (3认同)

小智 13

import java.util.Calendar;
import java.util.Date;

public class Main {
    public static long calculateDays(String startDate, String endDate)
    {
        Date sDate = new Date(startDate);
        Date eDate = new Date(endDate);
        Calendar cal3 = Calendar.getInstance();
        cal3.setTime(sDate);
        Calendar cal4 = Calendar.getInstance();
        cal4.setTime(eDate);
        return daysBetween(cal3, cal4);
    }

    public static void main(String[] args) {
        System.out.println(calculateDays("2012/03/31", "2012/06/17"));

    }

    /** Using Calendar - THE CORRECT WAY**/
    public static long daysBetween(Calendar startDate, Calendar endDate) {
        Calendar date = (Calendar) startDate.clone();
        long daysBetween = 0;
        while (date.before(endDate)) {
            date.add(Calendar.DAY_OF_MONTH, 1);
            daysBetween++;
        }
        return daysBetween;
    }
}
Run Code Online (Sandbox Code Playgroud)


ang*_*era 9

解决方案使用毫秒时间之间的差异,并正确舍入DST日期:

public static long daysDiff(Date from, Date to) {
    return daysDiff(from.getTime(), to.getTime());
}

public static long daysDiff(long from, long to) {
    return Math.round( (to - from) / 86400000D ); // 1000 * 60 * 60 * 24
}
Run Code Online (Sandbox Code Playgroud)

一个注意事项:当然,日期必须在某个时区.

重要的代码:

Math.round( (to - from) / 86400000D )
Run Code Online (Sandbox Code Playgroud)

如果你不想要圆,你可以使用UTC日期,