Android/Java - Date Difference in days

2018-12-31 15:53发布

I am getting the current date (in format 12/31/1999 i.e. mm/dd/yyyy) as using the below code:

Textview txtViewData;
txtViewDate.setText("Today is " +
        android.text.format.DateFormat.getDateFormat(this).format(new Date()));

and I am having another date in format as: 2010-08-25 (i.e. yyyy/mm/dd) ,

so I want to find the difference between date in number of days, how do I find difference in days?

(In other words, I want to find the difference between CURRENT DATE - yyyy/mm/dd formatted date)

17条回答
只靠听说
2楼-- · 2018-12-31 16:21

tl;dr

ChronoUnit.DAYS.between( 
    LocalDate.parse( "1999-12-28" ) , 
    LocalDate.parse( "12/31/1999" , DateTimeFormatter.ofPattern( "MM/dd/yyyy" ) ) 
)

Details

Other answers are outdated. The old date-time classes bundled with the earliest versions of Java have proven to be poorly designed, confusing, and troublesome. Avoid them.

java.time

The Joda-Time project was highly successful as a replacement for those old classes. These classes provided the inspiration for the java.time framework built into Java 8 and later.

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone.

Parsing strings

If your input strings are in standard ISO 8601 format, the LocalDate class can directly parse the string.

LocalDate start = LocalDate.parse( "1999-12-28" );

If not in ISO 8601 format, define a formatting pattern with DateTimeFormatter.

String input = "12/31/1999";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MM/dd/yyyy" );
LocalDate stop = LocalDate.parse( input , formatter );

Elapsed days via ChronoUnit

Now get a count of days elapsed between that pair of LocalDate objects. The ChronoUnit enum calculates elapsed time.

long totalDays = ChronoUnit.DAYS.between( start , stop ) ; 

If you are unfamiliar with Java enums, know they are far more powerful and useful that conventional enums in most other programming languages. See the Enum class doc, the Oracle Tutorial, and Wikipedia to learn more.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

查看更多
只靠听说
3楼-- · 2018-12-31 16:28

This is NOT my work, found the answer here. did not want a broken link in the future :).

The key is this line for taking daylight setting into account, ref Full Code.

TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));

or try passing TimeZone as a parameter to daysBetween() and call setTimeZone() in the sDate and eDate objects.

So here it goes:

public static Calendar getDatePart(Date date){
    Calendar cal = Calendar.getInstance();       // get calendar instance
    cal.setTime(date);      
    cal.set(Calendar.HOUR_OF_DAY, 0);            // set hour to midnight
    cal.set(Calendar.MINUTE, 0);                 // set minute in hour
    cal.set(Calendar.SECOND, 0);                 // set second in minute
    cal.set(Calendar.MILLISECOND, 0);            // set millisecond in second

    return cal;                                  // return the date part
}

getDatePart() taken from here

/**
 * This method also assumes endDate >= startDate
**/
public static long daysBetween(Date startDate, Date endDate) {
  Calendar sDate = getDatePart(startDate);
  Calendar eDate = getDatePart(endDate);

  long daysBetween = 0;
  while (sDate.before(eDate)) {
      sDate.add(Calendar.DAY_OF_MONTH, 1);
      daysBetween++;
  }
  return daysBetween;
}

The Nuances: Finding the difference between two dates isn't as straightforward as subtracting the two dates and dividing the result by (24 * 60 * 60 * 1000). Infact, its erroneous!

For example: The difference between the two dates 03/24/2007 and 03/25/2007 should be 1 day; However, using the above method, in the UK, you'll get 0 days!

See for yourself (code below). Going the milliseconds way will lead to rounding off errors and they become most evident once you have a little thing like Daylight Savings Time come into the picture.

Full Code:

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class DateTest {

public class DateTest {

static SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");

public static void main(String[] args) {

  TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));

  //diff between these 2 dates should be 1
  Date d1 = new Date("01/01/2007 12:00:00");
  Date d2 = new Date("01/02/2007 12:00:00");

  //diff between these 2 dates should be 1
  Date d3 = new Date("03/24/2007 12:00:00");
  Date d4 = new Date("03/25/2007 12:00:00");

  Calendar cal1 = Calendar.getInstance();cal1.setTime(d1);
  Calendar cal2 = Calendar.getInstance();cal2.setTime(d2);
  Calendar cal3 = Calendar.getInstance();cal3.setTime(d3);
  Calendar cal4 = Calendar.getInstance();cal4.setTime(d4);

  printOutput("Manual   ", d1, d2, calculateDays(d1, d2));
  printOutput("Calendar ", d1, d2, daysBetween(cal1, cal2));
  System.out.println("---");
  printOutput("Manual   ", d3, d4, calculateDays(d3, d4));
  printOutput("Calendar ", d3, d4, daysBetween(cal3, cal4));
}


private static void printOutput(String type, Date d1, Date d2, long result) {
  System.out.println(type+ "- Days between: " + sdf.format(d1)
                    + " and " + sdf.format(d2) + " is: " + result);
}

/** Manual Method - YIELDS INCORRECT RESULTS - DO NOT USE**/
/* This method is used to find the no of days between the given dates */
public static long calculateDays(Date dateEarly, Date dateLater) {
  return (dateLater.getTime() - dateEarly.getTime()) / (24 * 60 * 60 * 1000);
}

/** Using Calendar - THE CORRECT WAY**/
public static long daysBetween(Date startDate, Date endDate) {
  ...
}

OUTPUT:

Manual - Days between: 01-Jan-2007 and 02-Jan-2007 is: 1

Calendar - Days between: 01-Jan-2007 and 02-Jan-2007 is: 1


Manual - Days between: 24-Mar-2007 and 25-Mar-2007 is: 0

Calendar - Days between: 24-Mar-2007 and 25-Mar-2007 is: 1

查看更多
姐姐魅力值爆表
4楼-- · 2018-12-31 16:28

The Correct Way from Sam Quest's answer only works if the first date is earlier than the second. Moreover, it will return 1 if the two dates are within a single day.

This is the solution that worked best for me. Just like most other solutions, it would still show incorrect results on two days in a year because of wrong day light saving offset.

private final static long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;

long calculateDeltaInDays(Calendar a, Calendar b) {

    // Optional: avoid cloning objects if it is the same day
    if(a.get(Calendar.ERA) == b.get(Calendar.ERA) 
            && a.get(Calendar.YEAR) == b.get(Calendar.YEAR)
            && a.get(Calendar.DAY_OF_YEAR) == b.get(Calendar.DAY_OF_YEAR)) {
        return 0;
    }
    Calendar a2 = (Calendar) a.clone();
    Calendar b2 = (Calendar) b.clone();
    a2.set(Calendar.HOUR_OF_DAY, 0);
    a2.set(Calendar.MINUTE, 0);
    a2.set(Calendar.SECOND, 0);
    a2.set(Calendar.MILLISECOND, 0);
    b2.set(Calendar.HOUR_OF_DAY, 0);
    b2.set(Calendar.MINUTE, 0);
    b2.set(Calendar.SECOND, 0);
    b2.set(Calendar.MILLISECOND, 0);
    long diff = a2.getTimeInMillis() - b2.getTimeInMillis();
    long days = diff / MILLISECS_PER_DAY;
    return Math.abs(days);
}
查看更多
余欢
5楼-- · 2018-12-31 16:28
        Date userDob = new SimpleDateFormat("yyyy-MM-dd").parse(dob);
        Date today = new Date();
        long diff =  today.getTime() - userDob.getTime();
        int numOfDays = (int) (diff / (1000 * 60 * 60 * 24));
        int hours = (int) (diff / (1000 * 60 * 60));
        int minutes = (int) (diff / (1000 * 60));
        int seconds = (int) (diff / (1000));
查看更多
零度萤火
6楼-- · 2018-12-31 16:31

Use the following functions:

   /**
     * Returns the number of days between two dates. The time part of the
     * days is ignored in this calculation, so 2007-01-01 13:00 and 2007-01-02 05:00
     * have one day inbetween.
     */
    public static long daysBetween(Date firstDate, Date secondDate) {
        // We only use the date part of the given dates
        long firstSeconds = truncateToDate(firstDate).getTime()/1000;
        long secondSeconds = truncateToDate(secondDate).getTime()/1000;
        // Just taking the difference of the millis.
        // These will not be exactly multiples of 24*60*60, since there
        // might be daylight saving time somewhere inbetween. However, we can
        // say that by adding a half day and rounding down afterwards, we always
        // get the full days.
        long difference = secondSeconds-firstSeconds;
        // Adding half a day
        if( difference >= 0 ) {
            difference += SECONDS_PER_DAY/2; // plus half a day in seconds
        } else {
            difference -= SECONDS_PER_DAY/2; // minus half a day in seconds
        }
        // Rounding down to days
        difference /= SECONDS_PER_DAY;

        return difference;
    }

    /**
     * Truncates a date to the date part alone.
     */
    @SuppressWarnings("deprecation")
    public static Date truncateToDate(Date d) {
        if( d instanceof java.sql.Date ) {
            return d; // java.sql.Date is already truncated to date. And raises an
                      // Exception if we try to set hours, minutes or seconds.
        }
        d = (Date)d.clone();
        d.setHours(0);
        d.setMinutes(0);
        d.setSeconds(0);
        d.setTime(((d.getTime()/1000)*1000));
        return d;
    }
查看更多
登录 后发表回答