Android/Java - 以天为单位的日期差异

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3838527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 05:41:15  来源:igfitidea点击:

Android/Java - Date Difference in days

javaandroiddate

提问by Paresh Mayani

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

我使用以下代码获取当前日期(格式为 12/31/1999 即 mm/dd/yyyy):

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) ,

我还有另一个格式为:2010-08-25 (ie 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)

(换句话说,我想找到CURRENT DATE - yyyy/mm/dd 格式化日期之间的区别)

采纳答案by st0le

Not really a reliable method, better of using JodaTime

不是一个可靠的方法,最好使用JodaTime

  Calendar thatDay = Calendar.getInstance();
  thatDay.set(Calendar.DAY_OF_MONTH,25);
  thatDay.set(Calendar.MONTH,7); // 0-11 so 1 less
  thatDay.set(Calendar.YEAR, 1985);

  Calendar today = Calendar.getInstance();

  long diff = today.getTimeInMillis() - thatDay.getTimeInMillis(); //result in millis

Here's an approximation...

这是一个近似值...

long days = diff / (24 * 60 * 60 * 1000);

To Parse the date from a string, you could use

要从字符串中解析日期,您可以使用

  String strThatDay = "1985/08/25";
  SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
  Date d = null;
  try {
   d = formatter.parse(strThatDay);//catch exception
  } catch (ParseException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } 


  Calendar thatDay = Calendar.getInstance();
  thatDay.setTime(d); //rest is the same....

Although, since you're sure of the date format... You Could also do Integer.parseInt()on it's Substrings to obtain their numeric values.

虽然,因为你确定日期格式......你也可以Integer.parseInt()在它的子字符串上做以获得它们的数值。

回答by Daniel

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

回答by Jeroen Rosenberg

Use jodatime API

使用jodatime API

Days.daysBetween(start.toDateMidnight() , end.toDateMidnight() ).getDays() 

where 'start' and 'end' are your DateTimeobjects. To parse your date Strings into DateTime objects use the parseDateTime method

其中 'start' 和 'end' 是您的DateTime对象。要将日期字符串解析为 DateTime 对象,请使用parseDateTime 方法

There is also an android specific JodaTime library.

还有一个android 特定的 JodaTime 库

回答by Samuel

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 TimeZoneas a parameter to daysBetween()and call setTimeZone()in the sDateand eDateobjects.

或尝试通过TimeZone作为参数来daysBetween()和呼叫setTimeZone()sDateeDate对象。

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

getDatePart() 取自这里

/**
 * 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!

细微差别找出两个日期之间的差异并不像减去两个日期并将结果除以 (24 * 60 * 60 * 1000) 那样简单。事实上,它是错误的!

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!

例如:03/24/2007 和 03/25/2007 这两个日期之间的差应该是 1 天;但是,使用上述方法,在英国,您将获得0天!

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

手册 - 2007 年 1 月 1 日和 2007 年 1 月 2 日之间的天数为:1

日历 - 2007 年 1 月 1 日和 2007 年 1 月 2 日之间的天数为:1


手册 - 2007 年 3 月 24 日和 2007 年 3 月 25 日之间的天数为:0

日历 - 2007 年 3 月 24 日和 2007 年 3 月 25 日之间的天数为:1

回答by ccpizza

The Correct Wayfrom 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.

Correct Way萨姆任务的回答只有当第一个日期比第二早期的作品。此外,如果两个日期在一天之内,它将返回 1。

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

回答by markshiz

This fragment accounts for daylight savings time and is O(1).

该片段考虑了夏令时并且是 O(1)。

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

private static long getDateToLong(Date date) {
    return Date.UTC(date.getYear(), date.getMonth(), date.getDate(), 0, 0, 0);
}

public static int getSignedDiffInDays(Date beginDate, Date endDate) {
    long beginMS = getDateToLong(beginDate);
    long endMS = getDateToLong(endDate);
    long diff = (endMS - beginMS) / (MILLISECS_PER_DAY);
    return (int)diff;
}

public static int getUnsignedDiffInDays(Date beginDate, Date endDate) {
    return Math.abs(getSignedDiffInDays(beginDate, endDate));
}

回答by Gonan

I found a very easy way to do this and it's what I'm using in my app.

我找到了一种非常简单的方法来做到这一点,这就是我在我的应用程序中使用的方法。

Let's say you have the dates in Time objects (or whatever, we just need the milliseconds):

假设您在 Time 对象中有日期(或其他,我们只需要毫秒):

Time date1 = initializeDate1(); //get the date from somewhere
Time date2 = initializeDate2(); //get the date from somewhere

long millis1 = date1.toMillis(true);
long millis2 = date2.toMillis(true);

long difference = millis2 - millis1 ;

//now get the days from the difference and that's it
long days = TimeUnit.MILLISECONDS.toDays(difference);

//now you can do something like
if(days == 7)
{
    //do whatever when there's a week of difference
}

if(days >= 30)
{
    //do whatever when it's been a month or more
}

回答by zeh

There's a simple solution, that at least for me, is the only feasible solution.

有一个简单的解决方案,至少对我来说,是唯一可行的解​​决方案。

The problem is that all the answers I see being tossed around - using Joda, or Calendar, or Date, or whatever - only take the amount of milliseconds into consideration. They end up counting the number of 24-hour cycles between two dates, rather than the actual number of days. So something from Jan 1st 11pm to Jan 2nd 1am will return 0 days.

问题是我看到的所有答案都被扔了——使用 Joda、日历、日期或其他任何东西——只考虑了毫秒数。他们最终计算两个日期之间的 24 小时周期,而不是实际天数。因此,从 1 月 1 日晚上 11 点到 1 月 2 日凌晨 1 点的时间将返回 0 天。

To count the actual number of days between startDateand endDate, simply do:

要计算startDate和之间的实际天数endDate,只需执行以下操作:

// Find the sequential day from a date, essentially resetting time to start of the day
long startDay = startDate.getTime() / 1000 / 60 / 60 / 24;
long endDay = endDate.getTime() / 1000 / 60 / 60 / 24;

// Find the difference, duh
long daysBetween = endDay - startDay;

This will return "1" between Jan 2nd and Jan 1st. If you need to count the end day, just add 1 to daysBetween(I needed to do that in my code since I wanted to count the total number of days in the range).

这将在 1 月 2 日和 1 月 1 日之间返回“1”。如果您需要计算结束日期,只需将 1 添加到daysBetween(我需要在我的代码中这样做,因为我想计算范围内的总天数)。

This is somewhat similar to what Daniel has suggestedbut smaller code I suppose.

这有点类似于Daniel 的建议,但我认为代码较小。

回答by Lisa Anne

Most of the answers were good and right for your problem of

大多数答案都很好,适合您的问题

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

所以我想找到日期之间的天数差异,我如何找到天数差异?

I suggest this very simple and straightforward approach that is guaranteed to give you the correct difference in any time zone:

我建议采用这种非常简单直接的方法,可以保证在任何时区为您提供正确的差异:

int difference= 
((int)((startDate.getTime()/(24*60*60*1000))
-(int)(endDate.getTime()/(24*60*60*1000))));

And that's it!

就是这样!

回答by Rishi Gautam

This is Simple and best calculation for me and may be for you.

这对我来说是简单和最好的计算,可能也适合你。

       try {
            /// String CurrDate=  "10/6/2013";
            /// String PrvvDate=  "10/7/2013";
            Date date1 = null;
            Date date2 = null;
            SimpleDateFormat df = new SimpleDateFormat("M/dd/yyyy");
            date1 = df.parse(CurrDate);
            date2 = df.parse(PrvvDate);
            long diff = Math.abs(date1.getTime() - date2.getTime());
            long diffDays = diff / (24 * 60 * 60 * 1000);


            System.out.println(diffDays);

        } catch (Exception e1) {
            System.out.println("exception " + e1);
        }