50

I want to compare two dates for my Android application, but I got a really weird issue.

For example:

If I set the back in the past date to 127 days ago:

this.dateEvent = System.currentTimeMillis() - (127 * 24 * 3600 * 1000)

And then compare it to the current date (Days between)

    Calendar sDate = getDatePart(new Date(this.dateEvent));
    Calendar eDate = getDatePart(new Date(System.currentTimeMillis()));

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

    while (sDate.after(eDate))
    {
        eDate.add(Calendar.DAY_OF_MONTH, 1);
        daysBetween ++;
    }

    return daysBetween;

It will return 22 which is not at all what was expected.

Did I make something wrong or is that an issue with the Calendar class ?

4

18 回答 18

132

这是一个两行解决方案:

long msDiff = Calendar.getInstance().getTimeInMillis() - testCalendar.getTimeInMillis();
long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);

在此示例中,它获取日期“testCalendar”和当前日期之间的天数。

于 2016-06-06T14:12:51.510 回答
22

请参考此代码,这可能会对您有所帮助。

public String getCountOfDays(String createdDateString, String expireDateString) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());

    Date createdConvertedDate = null, expireCovertedDate = null, todayWithZeroTime = null;
    try {
        createdConvertedDate = dateFormat.parse(createdDateString);
        expireCovertedDate = dateFormat.parse(expireDateString);

        Date today = new Date();

        todayWithZeroTime = dateFormat.parse(dateFormat.format(today));
    } catch (ParseException e) {
        e.printStackTrace();
    }

    int cYear = 0, cMonth = 0, cDay = 0;

    if (createdConvertedDate.after(todayWithZeroTime)) {
        Calendar cCal = Calendar.getInstance();
        cCal.setTime(createdConvertedDate);
        cYear = cCal.get(Calendar.YEAR);
        cMonth = cCal.get(Calendar.MONTH);
        cDay = cCal.get(Calendar.DAY_OF_MONTH);

    } else {
        Calendar cCal = Calendar.getInstance();
        cCal.setTime(todayWithZeroTime);
        cYear = cCal.get(Calendar.YEAR);
        cMonth = cCal.get(Calendar.MONTH);
        cDay = cCal.get(Calendar.DAY_OF_MONTH);
    }


    /*Calendar todayCal = Calendar.getInstance();
    int todayYear = todayCal.get(Calendar.YEAR);
    int today = todayCal.get(Calendar.MONTH);
    int todayDay = todayCal.get(Calendar.DAY_OF_MONTH);
    */

    Calendar eCal = Calendar.getInstance();
    eCal.setTime(expireCovertedDate);

    int eYear = eCal.get(Calendar.YEAR);
    int eMonth = eCal.get(Calendar.MONTH);
    int eDay = eCal.get(Calendar.DAY_OF_MONTH);

    Calendar date1 = Calendar.getInstance();
    Calendar date2 = Calendar.getInstance();

    date1.clear();
    date1.set(cYear, cMonth, cDay);
    date2.clear();
    date2.set(eYear, eMonth, eDay);

    long diff = date2.getTimeInMillis() - date1.getTimeInMillis();

    float dayCount = (float) diff / (24 * 60 * 60 * 1000);

    return ("" + (int) dayCount + " Days");
}
于 2014-04-27T13:10:01.247 回答
9

我终于找到了解决这个问题的最简单方法。这是我的代码:

public int getTimeRemaining()
{
    Calendar sDate = toCalendar(this.dateEvent);
    Calendar eDate = toCalendar(System.currentTimeMillis());

    // Get the represented date in milliseconds
    long milis1 = sDate.getTimeInMillis();
    long milis2 = eDate.getTimeInMillis();

    // Calculate difference in milliseconds
    long diff = Math.abs(milis2 - milis1);

    return (int)(diff / (24 * 60 * 60 * 1000));
}

private Calendar toCalendar(long timestamp)
{
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(timestamp);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    return calendar;
}

希望能帮助到你。

于 2014-04-27T19:42:44.283 回答
9

你不应该使用这样的公式 24 * 60 * 60 * 1000!为什么?因为有节时间,并不是所有的日子都有 24 小时,闰年也有 +1 天。这就是为什么有一个日历类。如果您不想像 Jodatime 这样将任何外部库放入您的项目中,您可以使用具有非常高效功能的纯 Calendar 类:

public static int numDaysBetween(final Calendar c, final long fromTime, final long toTime) {
    int result = 0;
    if (toTime <= fromTime) return result;

    c.setTimeInMillis(toTime);
    final int toYear = c.get(Calendar.YEAR);
    result += c.get(Calendar.DAY_OF_YEAR);

    c.setTimeInMillis(fromTime);
    result -= c.get(Calendar.DAY_OF_YEAR);

    while (c.get(Calendar.YEAR) < toYear) {
        result += c.getActualMaximum(Calendar.DAY_OF_YEAR);
        c.add(Calendar.YEAR, 1);
    }

    return result;
}
于 2018-03-09T13:38:08.093 回答
7
public long Daybetween(String date1,String date2,String pattern)
{
    SimpleDateFormat sdf = new SimpleDateFormat(pattern,Locale.ENGLISH);
    Date Date1 = null,Date2 = null;
    try{
        Date1 = sdf.parse(date1);
        Date2 = sdf.parse(date2);
    }catch(Exception e)
    {
        e.printStackTrace();
    }
    return (Date2.getTime() - Date1.getTime())/(24*60*60*1000);
}
于 2016-03-03T04:04:05.980 回答
6
    Date userDob = new SimpleDateFormat("yyyy-MM-dd").parse(dob);
    Date today = new Date();
    long diff =  today.getTime() - userDob.getTime();
    int numOfYear = (int) ((diff / (1000 * 60 * 60 * 24))/365);
    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));
于 2016-11-26T08:52:07.633 回答
3

我也有同样的需求,最后我最终使用了 Joda Time,它非常方便并且提供了许多附加功能,包括您正在寻找的功能。

您可以从这里下载文件。

将 jar 文件包含到项目中后,您可以轻松地执行以下操作:

int daysBetween = Days.daysBetween(new DateTime(sDate), new DateTime(eDate)).getDays();
于 2014-04-27T14:26:37.493 回答
2

最好的方法 :-

        long fromCalender = Calender.getInstance();
        fromCalender.set...// set the from dates
        long toCalender = Calender.getInstance();
        fromCalender.set...// set the to dates

        long diffmili = fromCalender - toCalender;

        long hours = TimeUnit.MILLISECONDS.toHours(diffmili);
        long days = TimeUnit.MILLISECONDS.toDays(diffmili);
        long min = TimeUnit.MILLISECONDS.toMinutes(diffmili);
        long sec = TimeUnit.MILLISECONDS.toSeconds(diffmili);
于 2015-04-13T08:24:16.703 回答
2
fun TimeZone.daysBetween(from: Date, to: Date): Int {
    val offset = rawOffset + dstSavings
    return ((to.time + offset) / 86400000).toInt() - ((from.time + offset) / 86400000).toInt()
}

试试:

    val f = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").apply {
        timeZone = TimeZone.getTimeZone("GMT")
    }
    val df = f.parse("2019-02-28 22:59:59")
    val dt = f.parse("2019-02-28 23:00:00")

    TimeZone.getTimeZone("GMT").daysBetween(df, dt)  // 0
    TimeZone.getTimeZone("GMT+1").daysBetween(df, dt) // 1
于 2018-12-25T04:04:44.303 回答
2

这样做它支持所有 Api 级别

    Calendar cal = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy HH:mm:ss", 
    Locale.ENGLISH);
    try {
        String datestart="June 14 2018 16:02:37";
        cal.setTime(sdf.parse(datestart));// all done
         Calendar cal1=Calendar.getInstance();
        String formatted = sdf.format(cal1.getTime());//formatted date as i want
        cal1.setTime(sdf.parse(formatted));// all done

        long msDiff = cal1.getTimeInMillis() - cal.getTimeInMillis();
        long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);
        Toast.makeText(this, "days="+daysDiff, Toast.LENGTH_SHORT).show();
    } catch (ParseException e) {
        e.printStackTrace();
    }
于 2018-07-09T11:31:34.743 回答
2

java.time 和 ThreeTenABP

我想提供现代答案:使用 java.time,现代 Java 日期和时间 API 来处理您的日期工作。如果为 Android API 级别 25 或更低级别开发,则通过 Android 的 backport,ThreeTenABP(链接在底部)。

    LocalDate eDate = LocalDate.now(ZoneId.of("Europe/Paris"));
    LocalDate sDate = eDate.minusDays(127);

    long daysBetween = ChronoUnit.DAYS.between(sDate, eDate);
    System.out.println(daysBetween);

当我今天运行这段代码时,输​​出是预期的:

127

请注意,代码不仅更短,只需一行代码即可找到差异;阅读起来也更加清晰自然。您使用的类DateCalendar您使用的类设计不佳且早已过时。我建议你不要使用它们。

你的代码出了什么问题?

int将 127 天转换为毫秒时出现溢出。在数学中 127 * 24 * 3600 * 1000 等于 10 972 800 000。由于您相乘的数字是ints,Java 会执行 中的乘法int,并且可以容纳的最大数字int是 2 147 483 647,远远不足以达到您的预期结果。在这种情况下,如果 Java 会抛出异常或以其他方式让我们意识到错误,那就太好了。它没有。它默认丢弃高位,给我们的结果是 -1 912 101 888。从当前时间减去这个负数相当于增加了 22 天零几个小时。这就解释了为什么你得到 22。有趣的是,已经发布了 13 个答案,而且似乎没有人发现这个……</p>

即使使用该long类型进行乘法运算,它仍然不能正确计算 127 天。如果这 127 天与夏令时 (DST) 相互转换,在法国,一年 365 天中有 254 天就是这种情况,那么转换日不是 24 小时,而是 23 或 25 小时。这会导致不正确的毫秒数。

您应该始终将日期数学留给经过验证的库方法。永远不要自己手动编码。它比我们大多数人想象的要复杂,所以做错的风险很高。

问题:java.time 不需要 Android API 级别 26 吗?

java.time 在较旧和较新的 Android 设备上都能很好地工作。它只需要至少Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 开始)中,现代 API 是内置的。
  • 在非 Android Java 6 和 7 中获得 ThreeTen Backport,现代类的后向端口(ThreeTen 用于 JSR 310;请参阅底部的链接)。
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从org.threeten.bp子包中导入日期和时间类。

链接

于 2020-03-14T08:55:28.093 回答
1

Kotlin 扩展:

fun Date?.getDaysBetween(dest: Date?): Int {

    if(this == null || dest == null) return 0

    val diff = abs(this.time - dest.time)
    val dayCount = diff.toFloat() / (24 * 60 * 60 * 1000)
    return dayCount.toInt()
}
于 2020-06-30T10:51:36.737 回答
1

答案在“2019/02/18”、“2019/02/19”等日期不正确,但我编辑并解决了错误

这是最好的方法:

 public int getCountOfDays(String createdDateString, String expireDateString) {

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        Date createdConvertedDate = null;
        Date expireCovertedDate = null;
        try {
            createdConvertedDate = dateFormat.parse(createdDateString);
            expireCovertedDate = dateFormat.parse(expireDateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }


        Calendar start = new GregorianCalendar();
        start.setTime(createdConvertedDate);

        Calendar end = new GregorianCalendar();
        end.setTime(expireCovertedDate);

        long diff = end.getTimeInMillis() - start.getTimeInMillis();

        float dayCount = (float) diff / (24 * 60 * 60 * 1000);


        return (int) (dayCount);
    }

享受,如果有帮助的话+投票给这个答案;)

于 2018-04-09T08:04:07.647 回答
1

对我有用的最佳解决方案是:

private static int findDaysDiff(long unixStartTime,long unixEndTime)
    {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTimeInMillis(unixStartTime);
        calendar1.set(Calendar.HOUR_OF_DAY, 0);
        calendar1.set(Calendar.MINUTE, 0);
        calendar1.set(Calendar.SECOND, 0);
        calendar1.set(Calendar.MILLISECOND, 0);

        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTimeInMillis(unixEndTime);
        calendar2.set(Calendar.HOUR_OF_DAY, 0);
        calendar2.set(Calendar.MINUTE, 0);
        calendar2.set(Calendar.SECOND, 0);
        calendar2.set(Calendar.MILLISECOND, 0);

        return (int) ((calendar2.getTimeInMillis()-calendar1.getTimeInMillis())/(24 * 60 * 60 * 1000));

    }

由于它首先将Hour,和to转换为Minute,现在差异将仅以天为单位。SecondMillisecond0

于 2017-03-08T10:56:28.877 回答
0

这是非常适合我的 Java 8 java.time 版本。您可能需要确保 startDate 和 endDate 设置为相同的时间,否则天数可能会相差+-1! 这些是我刚刚复制/粘贴的 Kotlin 版本。

private fun getDawnOfDay(instant: Instant): Temporal =
        LocalDate.from(instant.atZone(ZoneOffset.UTC)).atStartOfDay()

fun getNumberOfDaysInBetween(startDate: Date, endDate: Date) =
        Duration.between(getDawnOfDay(startDate.toInstant()), getDawnOfDay(endDate.toInstant()))
            .toDays()
于 2020-06-17T09:56:11.377 回答
0

我计算上次提交日期和当前日期之间的天数,如果它小于零,那么学生不能提交。我正在与科特林合作。下面的代码可以帮助你。

 var calendar=Calendar.getInstance().time
 var dateFormat= SimpleDateFormat("dd/M/yyyy")
 var d2=dateFormat.parse(data.get("date").toString())
 var cd=dateFormat.format(calendar)
 var d1=dateFormat.parse(cd)
 var diff=d2.time-d1.time
 var ddd= TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS)
于 2019-04-01T06:40:20.183 回答
0

我刚刚修改了一些最受欢迎的答案。这是我的解决方案: daysBetween() - 返回两个日期之间的天数。

public static long daysBetween(Date date1, Date date2) {
        long msDiff = resetTimeToDateStart(date1).getTime() - resetTimeToDateStart(date2).getTime();
        return TimeUnit.MILLISECONDS.toDays(msDiff);
    }
private static Date resetTimeToDateStart(Date dDate){
        if (Utils.isNull(dDate)){
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dDate);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
于 2020-12-18T10:33:51.560 回答
0
int difference in days=(present_year - oldyear) * 365 + (present_month - oldmonth)*30 + (present_date-olddate);
于 2021-04-14T07:17:47.133 回答