在Java中,两个日期之间的天数有差异吗?

时间:2020-12-04 21:30:13

I need to find the number of days between two dates: one is from a report and one is the current date. My snippet:

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

  int age=calculateDifference(agingDate, today);

Here calculateDifference is a private method, agingDate and today are Date objects, just for your clarification. I've followed two articles from a Java forum, Thread 1 / Thread 2.

这里calculateDifference是一个私有方法,agingDate和today是Date对象,只是为了您的说明。我关注了Java论坛的两篇文章,线程1 /线程2。

It works fine in a standalone program although when I include this into my logic to read from the report I get an unusual difference in values.

它在单独的程序中工作得很好,但是当我将它包含到逻辑中以从报告中读取时,我得到了不同寻常的值差异。

Why is it happening and how can I fix it?

为什么会发生这样的事情,我该如何解决呢?

EDIT :

编辑:

I'm getting a greater number of days compared to the actual amount of Days.

我得到的天数比实际的天数要多。

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;
}

Note :

注意:

Unfortunately, none of the answers helped me solve the problem. I've accomplished this problem with the help of Joda-time library.

不幸的是,没有一个答案能帮助我解决这个问题。我在Joda-time图书馆的帮助下完成了这个问题。

20 个解决方案

#1


147  

I would suggest you use the excellent Joda Time library instead of the flawed java.util.Date and friends. You could simply write

我建议您使用优秀的Joda时间库,而不是有缺陷的java.util。和朋友约会。你可以简单地写

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

#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.");
  }

#3


23  

The diff / (24 * etc) does not take Timezone into account, so if your default timezone has a DST in it, it can throw the calculation off.

diff /(24 *等等)没有考虑到时区,所以如果您的默认时区中有一个DST,那么它可以将计算排除在外。

This link has a nice little implementation.

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

Here is the source of the above link in case the link goes down:

以下是上述连结的来源,以防连结失效:

/** 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;  
}  

and

/** 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;  
}

#4


14  

java.time

In Java 8 and later, use the java.time framework (Tutorial).

在Java 8和以后的版本中,使用Java。时间框架(教程)。

Duration

The Duration class represents a span of time as a number of seconds plus a fractional second. It can count days, hours, minutes, and seconds.

Duration类表示时间跨度为秒数加上小数秒。它可以计算天数、小时、分钟和秒。

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

ChronoUnit

If all you need is the number of days, alternatively you can use the ChronoUnit enum. Notice the calculation methods return a long rather than int.

如果您所需要的是天数,或者您可以使用时序枚举。注意,计算方法返回的是long而不是int。

long days = ChronoUnit.DAYS.between( then, now );

#5


13  

It depends on what you define as the difference. To compare two dates at midnight you can do.

这取决于你如何定义差异。要在午夜比较两个日期,你可以这样做。

long day1 = ...; // in milliseconds.
long day2 = ...; // in milliseconds.
long days = (day2 - day1) / 86400000;

#6


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;
    }
}

#7


9  

Solution using difference between milliseconds time, with correct rounding for DST dates:

解决方案使用毫秒间的差异,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
}

One note: Of course, dates must be in some timezone.

注意:当然,日期必须在某个时区。

The important code:

重要的代码:

Math.round( (to - from) / 86400000D )

If you don't want round, you can use UTC dates,

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

#8


4  

Illustration of the problem: (My code is computing delta in weeks, but same issue applies with delta in days)

问题的说明:(我的代码以周为单位计算增量,但以天为单位计算增量也存在同样的问题)

Here is a very reasonable-looking implementation:

这里有一个非常合理的实现:

public static final long MILLIS_PER_WEEK = 7L * 24L * 60L * 60L * 1000L;

static public int getDeltaInWeeks(Date latterDate, Date earlierDate) {
    long deltaInMillis = latterDate.getTime() - earlierDate.getTime();
    int deltaInWeeks = (int)(deltaInMillis / MILLIS_PER_WEEK);
    return deltaInWeeks; 
}

But this test will fail:

但是这个测试会失败:

public void testGetDeltaInWeeks() {
    delta = AggregatedData.getDeltaInWeeks(dateMar09, dateFeb23);
    assertEquals("weeks between Feb23 and Mar09", 2, delta);
}

The reason is:

原因是:

Mon Mar 09 00:00:00 EDT 2009 = 1,236,571,200,000
Mon Feb 23 00:00:00 EST 2009 = 1,235,365,200,000
MillisPerWeek = 604,800,000
Thus,
(Mar09 - Feb23) / MillisPerWeek =
1,206,000,000 / 604,800,000 = 1.994...

2009年2月23日美国东部时间2009年2月23日美国东部时间2009年1月23日

but anyone looking at a calendar would agree that the answer is 2.

但是任何看日历的人都会同意答案是2。

#9


3  

I use this funcion:

我用这个运输脂肪酸:

DATEDIFF("31/01/2016", "01/03/2016") // me return 30 days

my function:

我的函数:

import java.util.Date;

public long DATEDIFF(String date1, String date2) {
        long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;
        long days = 0l;
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); // "dd/MM/yyyy HH:mm:ss");

        Date dateIni = null;
        Date dateFin = null;        
        try {       
            dateIni = (Date) format.parse(date1);
            dateFin = (Date) format.parse(date2);
            days = (dateFin.getTime() - dateIni.getTime())/MILLISECS_PER_DAY;                        
        } catch (Exception e) {  e.printStackTrace();  }   

        return days; 
     }

#10


2  

Look at the getFragmentInDays methods in this apache commons-lang class DateUtils.

查看这个apache common -lang类DateUtils中的getFragmentInDays方法。

#11


2  

Based on @Mad_Troll's answer, I developed this method.

基于@Mad_Troll的答案,我开发了这个方法。

I've run about 30 test cases against it, is the only method that handles sub day time fragments correctly.

我已经运行了大约30个测试用例,这是唯一正确处理子日时间片段的方法。

Example: If you pass now & now + 1 millisecond that is still the same day. Doing 1-1-13 23:59:59.098 to 1-1-13 23:59:59.099 returns 0 days, correctly; allot of the other methods posted here will not do this correctly.

例子:如果你现在通过,现在+ 1毫秒,仍然是同一天。执行1-1-13 23:59:59.098到1-1-13 23:59:59.099返回0天,正确;在这里发布的其他方法将不能正确地执行此操作。

Worth noting it does not care about which way you put them in, If your end date is before your start date it will count backwards.

值得注意的是,它并不关心你把它们放在哪个位置,如果你的最终日期在你的开始日期之前,它会倒数。

/**
 * This is not quick but if only doing a few days backwards/forwards then it is very accurate.
 *
 * @param startDate from
 * @param endDate   to
 * @return day count between the two dates, this can be negative if startDate is after endDate
 */
public static long daysBetween(@NotNull final Calendar startDate, @NotNull final Calendar endDate) {

    //Forwards or backwards?
    final boolean forward = startDate.before(endDate);
    // Which direction are we going
    final int multiplier = forward ? 1 : -1;

    // The date we are going to move.
    final Calendar date = (Calendar) startDate.clone();

    // Result
    long daysBetween = 0;

    // Start at millis (then bump up until we go back a day)
    int fieldAccuracy = 4;
    int field;
    int dayBefore, dayAfter;
    while (forward && date.before(endDate) || !forward && endDate.before(date)) {
        // We start moving slowly if no change then we decrease accuracy.
        switch (fieldAccuracy) {
            case 4:
                field = Calendar.MILLISECOND;
                break;
            case 3:
                field = Calendar.SECOND;
                break;
            case 2:
                field = Calendar.MINUTE;
                break;
            case 1:
                field = Calendar.HOUR_OF_DAY;
                break;
            default:
            case 0:
                field = Calendar.DAY_OF_MONTH;
                break;
        }
        // Get the day before we move the time, Change, then get the day after.
        dayBefore = date.get(Calendar.DAY_OF_MONTH);
        date.add(field, multiplier);
        dayAfter = date.get(Calendar.DAY_OF_MONTH);

        // This shifts lining up the dates, one field at a time.
        if (dayBefore == dayAfter && date.get(field) == endDate.get(field))
            fieldAccuracy--;
        // If day has changed after moving at any accuracy level we bump the day counter.
        if (dayBefore != dayAfter) {
            daysBetween += multiplier;
        }
    }
    return daysBetween;
}

You can remove the @NotNull annotations, these are used by Intellij to do code analysis on the fly

您可以删除@NotNull注释,Intellij用来动态地进行代码分析

#12


1  

You say it "works fine in a standalone program," but that you get "unusual difference values" when you "include this into my logic to read from report". That suggests that your report has some values for which it doesn't work correctly, and your standalone program doesn't have those values. Instead of a standalone program, I suggest a test case. Write a test case much as you would a standalone program, subclassing from JUnit's TestCase class. Now you can run a very specific example, knowing what value you expect (and don't give it today for the test value, because today changes over time). If you put in the values you used in the standalone program, your tests will probably pass. That's great - you want those cases to keep working. Now, add a value from your report, one that doesn't work right. Your new test will probably fail. Figure out why it's failing, fix it, and get to green (all tests passing). Run your report. See what's still broken; write a test; make it pass. Pretty soon you'll find your report is working.

你说它“在一个独立的程序中工作得很好”,但是当你“把这个包含到我的逻辑中,从报告中读取”时,你会得到“不同寻常的值”。这表明您的报告有一些值,但它不能正确工作,而您的独立程序没有这些值。我建议一个测试用例,而不是一个独立的程序。编写一个测试用例,就像编写一个独立的程序一样,从JUnit的TestCase类进行子类化。现在,您可以运行一个非常特定的示例,了解您期望的值(今天不要为测试值提供它,因为今天随时间而变化)。如果您输入在独立程序中使用的值,您的测试可能会通过。那太好了——你希望这些案子继续运作。现在,从报表中添加一个不正确的值。你的新测试可能会失败。弄清楚为什么它会失败,修复它,然后转到绿色(所有测试都通过了)。运行您的报告。看看仍然破碎;编写一个测试;让它通过。很快你就会发现你的报告起作用了。

#13


1  

Hundred lines of code for this basic function???

这个基本函数的数百行代码???

Just a simple method:

只是一个简单的方法:

protected static int calculateDayDifference(Date dateAfter, Date dateBefore){
    return (int)(dateAfter.getTime()-dateBefore.getTime())/(1000 * 60 * 60 * 24); 
    // MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
}

#14


1  

public static int getDifferenceIndays(long timestamp1, long timestamp2) {
    final int SECONDS = 60;
    final int MINUTES = 60;
    final int HOURS = 24;
    final int MILLIES = 1000;
    long temp;
    if (timestamp1 < timestamp2) {
        temp = timestamp1;
        timestamp1 = timestamp2;
        timestamp2 = temp;
    }
    Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
    Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
    endDate.setTimeInMillis(timestamp1);
    startDate.setTimeInMillis(timestamp2);
    if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
        int day1 = endDate.get(Calendar.DAY_OF_MONTH);
        int day2 = startDate.get(Calendar.DAY_OF_MONTH);
        if (day1 == day2) {
            return 0;
        } else {
            return 1;
        }
    }
    int diffDays = 0;
    startDate.add(Calendar.DAY_OF_MONTH, diffDays);
    while (startDate.before(endDate)) {
        startDate.add(Calendar.DAY_OF_MONTH, 1);
        diffDays++;
    }
    return diffDays;
}

#15


1  

ThreeTen-Extra

The Answer by Vitalii Fedorenko is correct, describing how to perform this calculation in a modern way with java.time classes (Duration & ChronoUnit) built into Java 8 and later (and back-ported to Java 6 & 7 and to Android).

Vitalii Fedorenko的回答是正确的,他描述了如何使用java以一种现代的方式执行这个计算。时间类(Duration & ChronoUnit)构建到Java 8和更高版本(后端移植到Java 6和7以及Android)。

Days

If you are using a number of days routinely in your code, you can replace mere integers with use of a class. The Days class can be found in the ThreeTen-Extra project, an extension of java.time and proving ground for possible future additions to java.time. The Days class provides a type-safe way of representing a number of days in your application. The class includes convenient constants for ZERO and ONE.

如果您在代码中经常使用一些天数,那么您可以用类来替换仅仅是整数。Days类可以在三个额外的项目(java的扩展)中找到。时间和试验场,为将来可能添加到java.time。Days类提供了一种类型安全的方式来表示应用程序中的天数。该类包含0和1的方便常量。

Given the old outmoded java.util.Date objects in the Question, first convert them to modern java.time.Instant objects. The old date-time classes have newly added methods to facilitate conversion to java.time, such a java.util.Date::toInstant.

以过时的java为例。问题中的Date对象,首先将它们转换为现代java.time。即时对象。旧的日期-时间类有新添加的方法来促进对java的转换。时候,这样java.util.Date::toInstant。

Instant start = utilDateStart.toInstant(); // Inclusive.
Instant stop = utilDateStop.toInstant();  // Exclusive.

Pass both Instant objects to factory method for org.threeten.extra.Days.

将即时对象传递给工厂方法。

In the current implementation (2016-06) this is a wrapper calling java.time.temporal.ChronoUnit.DAYS.between, read the ChronoUnit class doc for details. To be clear: all uppercase DAYS is in the enum ChronoUnit while initial-cap Days is a class from ThreeTen-Extra.

在当前实现(2016-06)中,这是一个调用java.time.颞颥. chronounit . days的包装器。中间,阅读ChronoUnit类doc以获取详细信息。很明显:所有的大写日期都在枚举的时间内,而initialcap日是一个由3个额外的时间组成的类。

Days days = Days.between( start , stop );

You can pass these Days objects around your own code. You can serialize to a String in the standard ISO 8601 format by calling toString. This format of PnD uses a P to mark the beginning and D means “days”, with a number of days in between. Both java.time classes and ThreeTen-Extra use these standard formats by default when generating and parsing Strings representing date-time values.

现在,您可以在自己的代码中传递对象。您可以通过调用toString来序列化标准ISO 8601格式的字符串。这种PnD格式使用P来标记开始,D表示“天”,中间有几天。java。在生成和解析表示日期时间值的字符串时,默认情况下,时间类和three10额外使用这些标准格式。

String output = days.toString();

P3D

P3D

Days days = Days.parse( "P3D" );  

#16


0  

This code calculates days between 2 date Strings:

此代码计算两个日期字符串之间的天数:

    static final long MILLI_SECONDS_IN_A_DAY = 1000 * 60 * 60 * 24;
    static final String DATE_FORMAT = "dd-MM-yyyy";
    public long daysBetween(String fromDateStr, String toDateStr) throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
    Date fromDate;
    Date toDate;
    fromDate = format.parse(fromDateStr);
    toDate = format.parse(toDateStr);
    return (toDate.getTime() - fromDate.getTime()) / MILLI_SECONDS_IN_A_DAY;
}

#17


0  

If you're looking for a solution that returns proper number or days between e.g. 11/30/2014 23:59 and 12/01/2014 00:01 here's solution using Joda Time.

如果您正在寻找一个返回适当数字或天数的解决方案,例如:11/30/2014 23:59和12/01/2014 00:01之间。这里有使用Joda Time的解决方案。

private int getDayDifference(long past, long current) {
    DateTime currentDate = new DateTime(current);
    DateTime pastDate = new DateTime(past);
    return currentDate.getDayOfYear() - pastDate.getDayOfYear();
} 

This implementation will return 1 as a difference in days. Most of the solutions posted here calculate difference in milliseconds between two dates. It means that 0 would be returned because there's only 2 minutes difference between these two dates.

这个实现将返回1,作为天数的不同。这里发布的大多数解决方案都是计算两个日期之间的毫秒差。这意味着0将被返回,因为这两个日期之间只有2分钟的差异。

#18


0  

I've already written about it. This is a repost from Calculating the difference between two Java date instances.

我已经写过了。这是对计算两个Java日期实例之间的差异的一种回顾。

public int getDiffernceInDays(long timeAfter, long timeBefore) {
    Calendar calendarAfter = Calendar.getInstance();
    calendarAfter.setTime(new Date(timeAfter));

    Calendar calendarNewAfter = Calendar.getInstance();
    calendarNewAfter.set(calendarAfter.get(Calendar.YEAR), calendarAfter.get(Calendar.MONTH), calendarAfter.get(Calendar.DAY_OF_MONTH));

    Calendar calendarBefore = Calendar.getInstance();
    calendarBefore.setTime(new Date(timeBefore));

    Calendar calendarNewBefore = Calendar.getInstance();
    calendarNewBefore.set(calendarBefore.get(Calendar.YEAR), calendarBefore.get(Calendar.MONTH), calendarBefore.get(Calendar.DAY_OF_MONTH));

    return (int) ((calendarNewAfter.getTime().getTime() - calendarNewBefore.getTime().getTime()) / (24 * 60 * 60 * 1000));
}

#19


0  

You should use Joda Time library because Java Util Date returns wrong values sometimes.

您应该使用Joda时间库,因为Java Util Date有时会返回错误的值。

Joda vs Java Util Date

Joda vs Java Util Date

For example days between yesterday (dd-mm-yyyy, 12-07-2016) and first day of year in 1957 (dd-mm-yyyy, 01-01-1957):

例如,从昨天(dd-mm-yyy, 12-07-2016)到1957年的第一天(dd-mm- yyyyy, 01-01-1957):

public class Main {

public static void main(String[] args) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date date = null;
    try {
        date = format.parse("12-07-2016");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    //Try with Joda - prints 21742
    System.out.println("This is correct: " + getDaysBetweenDatesWithJodaFromYear1957(date));
    //Try with Java util - prints 21741
    System.out.println("This is not correct: " + getDaysBetweenDatesWithJavaUtilFromYear1957(date));    
}


private static int getDaysBetweenDatesWithJodaFromYear1957(Date date) {
    DateTime jodaDateTime = new DateTime(date);
    DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy");
    DateTime y1957 = formatter.parseDateTime("01-01-1957");

    return Days.daysBetween(y1957 , jodaDateTime).getDays();
}

private static long getDaysBetweenDatesWithJavaUtilFromYear1957(Date date) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date y1957 = null;
    try {
        y1957 = format.parse("01-01-1957");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return TimeUnit.DAYS.convert(date.getTime() - y1957.getTime(), TimeUnit.MILLISECONDS);
}

So I really advice you to use Joda Time library.

所以我真的建议你使用Joda Time library。

#20


-6  

I did it this way. it's easy :)

我是这样做的。很容易:)

Date d1 = jDateChooserFrom.getDate();
Date d2 = jDateChooserTo.getDate();

Calendar day1 = Calendar.getInstance();
day1.setTime(d1);

Calendar day2 = Calendar.getInstance();
day2.setTime(d2);

int from = day1.get(Calendar.DAY_OF_YEAR);
int to = day2.get(Calendar.DAY_OF_YEAR);

int difference = to-from;

#1


147  

I would suggest you use the excellent Joda Time library instead of the flawed java.util.Date and friends. You could simply write

我建议您使用优秀的Joda时间库,而不是有缺陷的java.util。和朋友约会。你可以简单地写

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

#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.");
  }

#3


23  

The diff / (24 * etc) does not take Timezone into account, so if your default timezone has a DST in it, it can throw the calculation off.

diff /(24 *等等)没有考虑到时区,所以如果您的默认时区中有一个DST,那么它可以将计算排除在外。

This link has a nice little implementation.

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

Here is the source of the above link in case the link goes down:

以下是上述连结的来源,以防连结失效:

/** 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;  
}  

and

/** 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;  
}

#4


14  

java.time

In Java 8 and later, use the java.time framework (Tutorial).

在Java 8和以后的版本中,使用Java。时间框架(教程)。

Duration

The Duration class represents a span of time as a number of seconds plus a fractional second. It can count days, hours, minutes, and seconds.

Duration类表示时间跨度为秒数加上小数秒。它可以计算天数、小时、分钟和秒。

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

ChronoUnit

If all you need is the number of days, alternatively you can use the ChronoUnit enum. Notice the calculation methods return a long rather than int.

如果您所需要的是天数,或者您可以使用时序枚举。注意,计算方法返回的是long而不是int。

long days = ChronoUnit.DAYS.between( then, now );

#5


13  

It depends on what you define as the difference. To compare two dates at midnight you can do.

这取决于你如何定义差异。要在午夜比较两个日期,你可以这样做。

long day1 = ...; // in milliseconds.
long day2 = ...; // in milliseconds.
long days = (day2 - day1) / 86400000;

#6


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;
    }
}

#7


9  

Solution using difference between milliseconds time, with correct rounding for DST dates:

解决方案使用毫秒间的差异,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
}

One note: Of course, dates must be in some timezone.

注意:当然,日期必须在某个时区。

The important code:

重要的代码:

Math.round( (to - from) / 86400000D )

If you don't want round, you can use UTC dates,

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

#8


4  

Illustration of the problem: (My code is computing delta in weeks, but same issue applies with delta in days)

问题的说明:(我的代码以周为单位计算增量,但以天为单位计算增量也存在同样的问题)

Here is a very reasonable-looking implementation:

这里有一个非常合理的实现:

public static final long MILLIS_PER_WEEK = 7L * 24L * 60L * 60L * 1000L;

static public int getDeltaInWeeks(Date latterDate, Date earlierDate) {
    long deltaInMillis = latterDate.getTime() - earlierDate.getTime();
    int deltaInWeeks = (int)(deltaInMillis / MILLIS_PER_WEEK);
    return deltaInWeeks; 
}

But this test will fail:

但是这个测试会失败:

public void testGetDeltaInWeeks() {
    delta = AggregatedData.getDeltaInWeeks(dateMar09, dateFeb23);
    assertEquals("weeks between Feb23 and Mar09", 2, delta);
}

The reason is:

原因是:

Mon Mar 09 00:00:00 EDT 2009 = 1,236,571,200,000
Mon Feb 23 00:00:00 EST 2009 = 1,235,365,200,000
MillisPerWeek = 604,800,000
Thus,
(Mar09 - Feb23) / MillisPerWeek =
1,206,000,000 / 604,800,000 = 1.994...

2009年2月23日美国东部时间2009年2月23日美国东部时间2009年1月23日

but anyone looking at a calendar would agree that the answer is 2.

但是任何看日历的人都会同意答案是2。

#9


3  

I use this funcion:

我用这个运输脂肪酸:

DATEDIFF("31/01/2016", "01/03/2016") // me return 30 days

my function:

我的函数:

import java.util.Date;

public long DATEDIFF(String date1, String date2) {
        long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;
        long days = 0l;
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); // "dd/MM/yyyy HH:mm:ss");

        Date dateIni = null;
        Date dateFin = null;        
        try {       
            dateIni = (Date) format.parse(date1);
            dateFin = (Date) format.parse(date2);
            days = (dateFin.getTime() - dateIni.getTime())/MILLISECS_PER_DAY;                        
        } catch (Exception e) {  e.printStackTrace();  }   

        return days; 
     }

#10


2  

Look at the getFragmentInDays methods in this apache commons-lang class DateUtils.

查看这个apache common -lang类DateUtils中的getFragmentInDays方法。

#11


2  

Based on @Mad_Troll's answer, I developed this method.

基于@Mad_Troll的答案,我开发了这个方法。

I've run about 30 test cases against it, is the only method that handles sub day time fragments correctly.

我已经运行了大约30个测试用例,这是唯一正确处理子日时间片段的方法。

Example: If you pass now & now + 1 millisecond that is still the same day. Doing 1-1-13 23:59:59.098 to 1-1-13 23:59:59.099 returns 0 days, correctly; allot of the other methods posted here will not do this correctly.

例子:如果你现在通过,现在+ 1毫秒,仍然是同一天。执行1-1-13 23:59:59.098到1-1-13 23:59:59.099返回0天,正确;在这里发布的其他方法将不能正确地执行此操作。

Worth noting it does not care about which way you put them in, If your end date is before your start date it will count backwards.

值得注意的是,它并不关心你把它们放在哪个位置,如果你的最终日期在你的开始日期之前,它会倒数。

/**
 * This is not quick but if only doing a few days backwards/forwards then it is very accurate.
 *
 * @param startDate from
 * @param endDate   to
 * @return day count between the two dates, this can be negative if startDate is after endDate
 */
public static long daysBetween(@NotNull final Calendar startDate, @NotNull final Calendar endDate) {

    //Forwards or backwards?
    final boolean forward = startDate.before(endDate);
    // Which direction are we going
    final int multiplier = forward ? 1 : -1;

    // The date we are going to move.
    final Calendar date = (Calendar) startDate.clone();

    // Result
    long daysBetween = 0;

    // Start at millis (then bump up until we go back a day)
    int fieldAccuracy = 4;
    int field;
    int dayBefore, dayAfter;
    while (forward && date.before(endDate) || !forward && endDate.before(date)) {
        // We start moving slowly if no change then we decrease accuracy.
        switch (fieldAccuracy) {
            case 4:
                field = Calendar.MILLISECOND;
                break;
            case 3:
                field = Calendar.SECOND;
                break;
            case 2:
                field = Calendar.MINUTE;
                break;
            case 1:
                field = Calendar.HOUR_OF_DAY;
                break;
            default:
            case 0:
                field = Calendar.DAY_OF_MONTH;
                break;
        }
        // Get the day before we move the time, Change, then get the day after.
        dayBefore = date.get(Calendar.DAY_OF_MONTH);
        date.add(field, multiplier);
        dayAfter = date.get(Calendar.DAY_OF_MONTH);

        // This shifts lining up the dates, one field at a time.
        if (dayBefore == dayAfter && date.get(field) == endDate.get(field))
            fieldAccuracy--;
        // If day has changed after moving at any accuracy level we bump the day counter.
        if (dayBefore != dayAfter) {
            daysBetween += multiplier;
        }
    }
    return daysBetween;
}

You can remove the @NotNull annotations, these are used by Intellij to do code analysis on the fly

您可以删除@NotNull注释,Intellij用来动态地进行代码分析

#12


1  

You say it "works fine in a standalone program," but that you get "unusual difference values" when you "include this into my logic to read from report". That suggests that your report has some values for which it doesn't work correctly, and your standalone program doesn't have those values. Instead of a standalone program, I suggest a test case. Write a test case much as you would a standalone program, subclassing from JUnit's TestCase class. Now you can run a very specific example, knowing what value you expect (and don't give it today for the test value, because today changes over time). If you put in the values you used in the standalone program, your tests will probably pass. That's great - you want those cases to keep working. Now, add a value from your report, one that doesn't work right. Your new test will probably fail. Figure out why it's failing, fix it, and get to green (all tests passing). Run your report. See what's still broken; write a test; make it pass. Pretty soon you'll find your report is working.

你说它“在一个独立的程序中工作得很好”,但是当你“把这个包含到我的逻辑中,从报告中读取”时,你会得到“不同寻常的值”。这表明您的报告有一些值,但它不能正确工作,而您的独立程序没有这些值。我建议一个测试用例,而不是一个独立的程序。编写一个测试用例,就像编写一个独立的程序一样,从JUnit的TestCase类进行子类化。现在,您可以运行一个非常特定的示例,了解您期望的值(今天不要为测试值提供它,因为今天随时间而变化)。如果您输入在独立程序中使用的值,您的测试可能会通过。那太好了——你希望这些案子继续运作。现在,从报表中添加一个不正确的值。你的新测试可能会失败。弄清楚为什么它会失败,修复它,然后转到绿色(所有测试都通过了)。运行您的报告。看看仍然破碎;编写一个测试;让它通过。很快你就会发现你的报告起作用了。

#13


1  

Hundred lines of code for this basic function???

这个基本函数的数百行代码???

Just a simple method:

只是一个简单的方法:

protected static int calculateDayDifference(Date dateAfter, Date dateBefore){
    return (int)(dateAfter.getTime()-dateBefore.getTime())/(1000 * 60 * 60 * 24); 
    // MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
}

#14


1  

public static int getDifferenceIndays(long timestamp1, long timestamp2) {
    final int SECONDS = 60;
    final int MINUTES = 60;
    final int HOURS = 24;
    final int MILLIES = 1000;
    long temp;
    if (timestamp1 < timestamp2) {
        temp = timestamp1;
        timestamp1 = timestamp2;
        timestamp2 = temp;
    }
    Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
    Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
    endDate.setTimeInMillis(timestamp1);
    startDate.setTimeInMillis(timestamp2);
    if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
        int day1 = endDate.get(Calendar.DAY_OF_MONTH);
        int day2 = startDate.get(Calendar.DAY_OF_MONTH);
        if (day1 == day2) {
            return 0;
        } else {
            return 1;
        }
    }
    int diffDays = 0;
    startDate.add(Calendar.DAY_OF_MONTH, diffDays);
    while (startDate.before(endDate)) {
        startDate.add(Calendar.DAY_OF_MONTH, 1);
        diffDays++;
    }
    return diffDays;
}

#15


1  

ThreeTen-Extra

The Answer by Vitalii Fedorenko is correct, describing how to perform this calculation in a modern way with java.time classes (Duration & ChronoUnit) built into Java 8 and later (and back-ported to Java 6 & 7 and to Android).

Vitalii Fedorenko的回答是正确的,他描述了如何使用java以一种现代的方式执行这个计算。时间类(Duration & ChronoUnit)构建到Java 8和更高版本(后端移植到Java 6和7以及Android)。

Days

If you are using a number of days routinely in your code, you can replace mere integers with use of a class. The Days class can be found in the ThreeTen-Extra project, an extension of java.time and proving ground for possible future additions to java.time. The Days class provides a type-safe way of representing a number of days in your application. The class includes convenient constants for ZERO and ONE.

如果您在代码中经常使用一些天数,那么您可以用类来替换仅仅是整数。Days类可以在三个额外的项目(java的扩展)中找到。时间和试验场,为将来可能添加到java.time。Days类提供了一种类型安全的方式来表示应用程序中的天数。该类包含0和1的方便常量。

Given the old outmoded java.util.Date objects in the Question, first convert them to modern java.time.Instant objects. The old date-time classes have newly added methods to facilitate conversion to java.time, such a java.util.Date::toInstant.

以过时的java为例。问题中的Date对象,首先将它们转换为现代java.time。即时对象。旧的日期-时间类有新添加的方法来促进对java的转换。时候,这样java.util.Date::toInstant。

Instant start = utilDateStart.toInstant(); // Inclusive.
Instant stop = utilDateStop.toInstant();  // Exclusive.

Pass both Instant objects to factory method for org.threeten.extra.Days.

将即时对象传递给工厂方法。

In the current implementation (2016-06) this is a wrapper calling java.time.temporal.ChronoUnit.DAYS.between, read the ChronoUnit class doc for details. To be clear: all uppercase DAYS is in the enum ChronoUnit while initial-cap Days is a class from ThreeTen-Extra.

在当前实现(2016-06)中,这是一个调用java.time.颞颥. chronounit . days的包装器。中间,阅读ChronoUnit类doc以获取详细信息。很明显:所有的大写日期都在枚举的时间内,而initialcap日是一个由3个额外的时间组成的类。

Days days = Days.between( start , stop );

You can pass these Days objects around your own code. You can serialize to a String in the standard ISO 8601 format by calling toString. This format of PnD uses a P to mark the beginning and D means “days”, with a number of days in between. Both java.time classes and ThreeTen-Extra use these standard formats by default when generating and parsing Strings representing date-time values.

现在,您可以在自己的代码中传递对象。您可以通过调用toString来序列化标准ISO 8601格式的字符串。这种PnD格式使用P来标记开始,D表示“天”,中间有几天。java。在生成和解析表示日期时间值的字符串时,默认情况下,时间类和three10额外使用这些标准格式。

String output = days.toString();

P3D

P3D

Days days = Days.parse( "P3D" );  

#16


0  

This code calculates days between 2 date Strings:

此代码计算两个日期字符串之间的天数:

    static final long MILLI_SECONDS_IN_A_DAY = 1000 * 60 * 60 * 24;
    static final String DATE_FORMAT = "dd-MM-yyyy";
    public long daysBetween(String fromDateStr, String toDateStr) throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
    Date fromDate;
    Date toDate;
    fromDate = format.parse(fromDateStr);
    toDate = format.parse(toDateStr);
    return (toDate.getTime() - fromDate.getTime()) / MILLI_SECONDS_IN_A_DAY;
}

#17


0  

If you're looking for a solution that returns proper number or days between e.g. 11/30/2014 23:59 and 12/01/2014 00:01 here's solution using Joda Time.

如果您正在寻找一个返回适当数字或天数的解决方案,例如:11/30/2014 23:59和12/01/2014 00:01之间。这里有使用Joda Time的解决方案。

private int getDayDifference(long past, long current) {
    DateTime currentDate = new DateTime(current);
    DateTime pastDate = new DateTime(past);
    return currentDate.getDayOfYear() - pastDate.getDayOfYear();
} 

This implementation will return 1 as a difference in days. Most of the solutions posted here calculate difference in milliseconds between two dates. It means that 0 would be returned because there's only 2 minutes difference between these two dates.

这个实现将返回1,作为天数的不同。这里发布的大多数解决方案都是计算两个日期之间的毫秒差。这意味着0将被返回,因为这两个日期之间只有2分钟的差异。

#18


0  

I've already written about it. This is a repost from Calculating the difference between two Java date instances.

我已经写过了。这是对计算两个Java日期实例之间的差异的一种回顾。

public int getDiffernceInDays(long timeAfter, long timeBefore) {
    Calendar calendarAfter = Calendar.getInstance();
    calendarAfter.setTime(new Date(timeAfter));

    Calendar calendarNewAfter = Calendar.getInstance();
    calendarNewAfter.set(calendarAfter.get(Calendar.YEAR), calendarAfter.get(Calendar.MONTH), calendarAfter.get(Calendar.DAY_OF_MONTH));

    Calendar calendarBefore = Calendar.getInstance();
    calendarBefore.setTime(new Date(timeBefore));

    Calendar calendarNewBefore = Calendar.getInstance();
    calendarNewBefore.set(calendarBefore.get(Calendar.YEAR), calendarBefore.get(Calendar.MONTH), calendarBefore.get(Calendar.DAY_OF_MONTH));

    return (int) ((calendarNewAfter.getTime().getTime() - calendarNewBefore.getTime().getTime()) / (24 * 60 * 60 * 1000));
}

#19


0  

You should use Joda Time library because Java Util Date returns wrong values sometimes.

您应该使用Joda时间库,因为Java Util Date有时会返回错误的值。

Joda vs Java Util Date

Joda vs Java Util Date

For example days between yesterday (dd-mm-yyyy, 12-07-2016) and first day of year in 1957 (dd-mm-yyyy, 01-01-1957):

例如,从昨天(dd-mm-yyy, 12-07-2016)到1957年的第一天(dd-mm- yyyyy, 01-01-1957):

public class Main {

public static void main(String[] args) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date date = null;
    try {
        date = format.parse("12-07-2016");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    //Try with Joda - prints 21742
    System.out.println("This is correct: " + getDaysBetweenDatesWithJodaFromYear1957(date));
    //Try with Java util - prints 21741
    System.out.println("This is not correct: " + getDaysBetweenDatesWithJavaUtilFromYear1957(date));    
}


private static int getDaysBetweenDatesWithJodaFromYear1957(Date date) {
    DateTime jodaDateTime = new DateTime(date);
    DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy");
    DateTime y1957 = formatter.parseDateTime("01-01-1957");

    return Days.daysBetween(y1957 , jodaDateTime).getDays();
}

private static long getDaysBetweenDatesWithJavaUtilFromYear1957(Date date) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date y1957 = null;
    try {
        y1957 = format.parse("01-01-1957");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return TimeUnit.DAYS.convert(date.getTime() - y1957.getTime(), TimeUnit.MILLISECONDS);
}

So I really advice you to use Joda Time library.

所以我真的建议你使用Joda Time library。

#20


-6  

I did it this way. it's easy :)

我是这样做的。很容易:)

Date d1 = jDateChooserFrom.getDate();
Date d2 = jDateChooserTo.getDate();

Calendar day1 = Calendar.getInstance();
day1.setTime(d1);

Calendar day2 = Calendar.getInstance();
day2.setTime(d2);

int from = day1.get(Calendar.DAY_OF_YEAR);
int to = day2.get(Calendar.DAY_OF_YEAR);

int difference = to-from;