简体   繁体   English

Android 计算两个日期之间的天数

[英]Android calculate days between two dates

I have written the following code to find days between two dates我编写了以下代码来查找两个日期之间的天数

    startDateValue = new Date(startDate);
    endDateValue = new Date(endDate);
    long diff = endDateValue.getTime() - startDateValue.getTime();
    long seconds = diff / 1000;
    long minutes = seconds / 60;
    long hours = minutes / 60;
    long days = (hours / 24) + 1;
    Log.d("days", "" + days);

When start and end date are 2/3/2017 and 3/3/2017 respectively the number of days showing is 29.Though when they are of the same day it is showing 1.(The number of days one takes a leave.So if one takes a single day leave,he has to select same start and end date.So in this case he has taken two days leave).当开始日期和结束日期分别为 2/3/2017 和 3/3/2017 时,显示的天数为 29。虽然当它们在同一天时,它显示 1。(请假的天数。所以如果一个人只休一天假,他必须 select 相同的开始和结束日期。所以在这种情况下,他已经休了两天假)。

What am I doing wrong?我究竟做错了什么? Thank you for your time.感谢您的时间。

Note: Please don't use the date constructor.注意:请不要使用日期构造函数。 Check the accepted answer below.检查下面接受的答案。 Use simpledateformat or Joda time.使用 simpledateformat 或 Joda 时间。 Date constructor is deprecated.日期构造函数已弃用。

Your code for generating date object:您生成日期对象的代码:

Date date = new Date("2/3/2017"); //deprecated

You are getting 28 days as answer because according to Date(String) constructor it is thinking day = 3,month = 2 and year = 2017您得到 28 天作为答案,因为根据Date(String)构造函数,它正在考虑 day = 3,month = 2 and year = 2017

You can convert String to Date as follows:您可以按如下方式将字符串转换为日期:

String dateStr = "2/3/2017";
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date date = sdf.parse(dateStr);

Use above template to make your Date object.使用上面的模板来制作你的 Date 对象。 Then use below code for calculating days in between two dates.然后使用下面的代码计算两个日期之间的天数。 Hope this clear the thing.希望这清楚的事情。

It can de done as follows:它可以按如下方式完成:

long diff = endDateValue.getTime() - startDateValue.getTime();
System.out.println ("Days: " + TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS));

Please check link请检查链接

If you use Joda Time it is much more simple:如果您使用 Joda Time,它会简单得多:

int days = Days.daysBetween(date1, date2).getDays();

Please check JodaTime请检查JodaTime

How to use JodaTime in Java Project 如何在 Java 项目中使用 JodaTime

Kotlin科特林

Here is the example to calculate days from today to some date:以下是计算从今天到某个日期的天数的示例:

 val millionSeconds = yourDate.time - Calendar.getInstance().timeInMillis
 leftDays.text = TimeUnit.MILLISECONDS.toDays(millionSeconds).toString() + "days"

If you want to calculate two days, then change:如果要计算两天,则更改:

val millionSeconds = yourDate1.time - yourDate2.time

should work.应该管用。

public static int getDaysDifference(Date fromDate,Date toDate)
{
if(fromDate==null||toDate==null)
return 0;

return (int)( (toDate.getTime() - fromDate.getTime()) / (1000 * 60 * 60 * 24));
}

Does Android fully support java-8 ? Android是否完全支持java-8 If yes you can simple use ChronoUnit class如果是,您可以简单地使用ChronoUnit

LocalDate start = LocalDate.of(2017,2,3);
LocalDate end = LocalDate.of(2017,3,3);

System.out.println(ChronoUnit.DAYS.between(start, end)); // 28

or same thing using formatter或者同样的事情使用格式化程序

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy");
LocalDate start = LocalDate.parse("2/3/2017",formatter);
LocalDate end = LocalDate.parse("3/3/2017",formatter);

System.out.println(ChronoUnit.DAYS.between(start, end)); // 28

What date format do you use?你使用什么日期格式? Is it d/M/yyyy or M/d/yyyy ?d/M/yyyy还是M/d/yyyy

d = day, M = month, yyyy = year d = 日,M = 月,yyyy = 年

(see: https://developer.android.com/reference/java/text/SimpleDateFormat.html ) (参见: https : //developer.android.com/reference/java/text/SimpleDateFormat.html

Then the codes:然后是代码:

public static final String DATE_FORMAT = "d/M/yyyy";  //or use "M/d/yyyy"   

public static long getDaysBetweenDates(String start, String end) {
    SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH);
    Date startDate, endDate;
    long numberOfDays = 0;
    try {
        startDate = dateFormat.parse(start);
        endDate = dateFormat.parse(end);
        numberOfDays = getUnitBetweenDates(startDate, endDate, TimeUnit.DAYS);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return numberOfDays;
}

And for getUnitBetweenDates method:对于getUnitBetweenDates方法:

private static long getUnitBetweenDates(Date startDate, Date endDate, TimeUnit unit) {
    long timeDiff = endDate.getTime() - startDate.getTime();
    return unit.convert(timeDiff, TimeUnit.MILLISECONDS);
}

Have look at this code , this is helpful for me ,hope it will help you.看看这段代码,这对我有帮助,希望它能帮助你。

public String get_count_of_days(String Created_date_String, String Expire_date_String) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());

Date Created_convertedDate = null, Expire_CovertedDate = null, todayWithZeroTime = null;
try {
    Created_convertedDate = dateFormat.parse(Created_date_String);
    Expire_CovertedDate = dateFormat.parse(Expire_date_String);

    Date today = new Date();

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

int c_year = 0, c_month = 0, c_day = 0;

if (Created_convertedDate.after(todayWithZeroTime)) {
    Calendar c_cal = Calendar.getInstance();
    c_cal.setTime(Created_convertedDate);
    c_year = c_cal.get(Calendar.YEAR);
    c_month = c_cal.get(Calendar.MONTH);
    c_day = c_cal.get(Calendar.DAY_OF_MONTH);

} else {
    Calendar c_cal = Calendar.getInstance();
    c_cal.setTime(todayWithZeroTime);
    c_year = c_cal.get(Calendar.YEAR);
    c_month = c_cal.get(Calendar.MONTH);
    c_day = c_cal.get(Calendar.DAY_OF_MONTH);
}


/*Calendar today_cal = Calendar.getInstance();
int today_year = today_cal.get(Calendar.YEAR);
int today = today_cal.get(Calendar.MONTH);
int today_day = today_cal.get(Calendar.DAY_OF_MONTH);
*/

Calendar e_cal = Calendar.getInstance();
e_cal.setTime(Expire_CovertedDate);

int e_year = e_cal.get(Calendar.YEAR);
int e_month = e_cal.get(Calendar.MONTH);
int e_day = e_cal.get(Calendar.DAY_OF_MONTH);

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

date1.clear();
date1.set(c_year, c_month, c_day);
date2.clear();
date2.set(e_year, e_month, e_day);

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

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

return ("" + (int) dayCount + " Days");

} }

Very simple, just use Calendar, create two instances for the two dates, convert to milliseconds, subtract and convert to days (rounded up)... like this, basically:很简单,只需使用Calendar,为两个日期创建两个实例,转换为毫秒,减去并转换为天(四舍五入)......像这样,基本上:

Calendar startDate = Calendar.getInstance();
startDate.set(mStartYear, mStartMonth, mStartDay);
long startDateMillis = startDate.getTimeInMillis();

Calendar endDate = Calendar.getInstance();
endDate.set(mEndYear, mEndMonth, mEndDay);
long endDateMillis = endDate.getTimeInMillis();

long differenceMillis = endDateMillis - startDateMillis;
int daysDifference = (int) (differenceMillis / (1000 * 60 * 60 * 24));

java.time and ThreeTenABP java.time 和 ThreeTenABP

If I understand correctly, you want the number of days from start day through end date inclusive .如果我理解正确,您需要从开始日期到结束日期的天数(包括)

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("d/M/u");

    String startDate = "2/3/2017";
    String endDate = "3/3/2017";

    LocalDate startDateValue = LocalDate.parse(startDate, dateFormatter);
    LocalDate endDateValue = LocalDate.parse(endDate, dateFormatter);
    long days = ChronoUnit.DAYS.between(startDateValue, endDateValue) + 1;

    System.out.println("Days: " + days);

Output:输出:

Days: 2天数:2

ChronoUnit.DAYS.between() gives us a count of days from start date inclusive to end date exclusive . ChronoUnit.DAYS.between()为我们提供了从包含开始日期到包含结束日期的天数。 So to include the end date too we needed to add 1 day just as you did in the question.因此,为了也包括结束日期,我们需要像您在问题中所做的那样添加 1 天。

What went wrong in your code?你的代码出了什么问题?

You are using the Date(String) constructor.您正在使用Date(String)构造函数。 This constructor has been deprecated since 1997 because it works unreliably across time zones, so don't use it.自 1997 年以来,此构造函数已被弃用,因为它跨时区工作不可靠,因此请勿使用它。 Also it's kind of magical: at least I never really know what I get.这也有点神奇:至少我从来不知道我得到了什么。 Apparently it takes 2/3/2017 to mean February 3, 2017, where you intended 2 March 2017. From February 3 to March 3 inclusive is 29 days (since 2017 wasn't a leap year).显然,这需要2/3/2017是指2017年2月3日,在那里你2017年三月预期的2从2月3日至3月3日包容性为29天(2017年以来是不是闰年)。 This explains why you got 29. (If necessary, we could spell our way through the documentation and find out why 2/3/2017 is interpreted the way it is, only I'd find that a pointless waste of time to do.)这解释了为什么你得到了 29。(如果有必要,我们可以通过文档拼写我们的方式并找出为什么2/3/2017被解释成这样,只有我会发现这是毫无意义的浪费时间。)

You can't convert from milliseconds.你不能从毫秒转换。 Please also note that not only the question but also the very many answers that convert from milliseconds to days are incorrect.另请注意,不仅是问题,而且从毫秒转换为天的许多答案都是不正确的。 Such a conversion assumes that a day is always 24 hours.这种转换假设一天总是 24 小时。 Because of summer time (DST) and other time anomalies a day is not always 24 hours.由于夏令时 (DST) 和其他时间异常,一天并不总是 24 小时。 All of those answers will count a day too few for example if the leave crosses the spring gap or spring forward when summer time begins.例如,如果休假跨越春季间隙或在夏季开始时向前推进,那么所有这些答案都将计入太少的一天。

Question: Doesn't java.time require Android API level 26?问题:java.time 不需要 Android API 级别 26 吗?

java.time works nicely on both older and newer Android devices. java.time 在较旧和较新的 Android 设备上都能很好地工作。 It just requires at least Java 6 .它只需要至少Java 6

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.在 Java 8 及更高版本和更新的 Android 设备(从 API 级别 26)中,现代 API 是内置的。
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).在非 Android Java 6 和 7 中获得 ThreeTen Backport,现代类的 backport(ThreeTen for JSR 310;请参阅底部的链接)。
  • On (older) Android use the Android edition of ThreeTen Backport.在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。 It's called ThreeTenABP.它被称为 ThreeTenABP。 And make sure you import the date and time classes from org.threeten.bp with subpackages.并确保使用子包从org.threeten.bp导入日期和时间类。

Links链接

Be carefur if you'd like to use received integer eg to indicate specific day in custom calendar implementation.如果您想使用接收到的整数,例如在自定义日历实现中指示特定日期,请小心。 For example, I tried to go in m app from monthly calendar view to daily view and show daily content, by calculating dates from 1970-01-01 to selected one, and each 25-31th day of month shows me as one day earlier, because datesDifferenceInMillis / (24 * 60 * 60 * 1000);例如,我尝试在 m app 中从月历视图进入每日视图并显示每日内容,通过计算从 1970-01-01 到选定日期的日期,每个月的第 25-31 天将我显示为前一天,因为datesDifferenceInMillis / (24 * 60 * 60 * 1000); may return something like 17645,95833333333, and casting this to int you'll get value lower by 1. In this case correctly number of days you'll get by rounding received float by using NumberFormat class.可能会返回类似 17645,95833333333 的内容,并将其转换为 int,您将得到的值降低 1。在这种情况下,您可以通过使用 NumberFormat 类对接收到的浮点数进行四舍五入来获得正确的天数。 Here's my code:这是我的代码:

NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault());
numberFormat.setRoundingMode(RoundingMode.HALF_UP);
numberFormat.setMaximumFractionDigits(0);
numberFormat.setMinimumFractionDigits(0);
int days = numberFormat.parse(numberFormat.format(value)).intValue();

I hope it will be helpful.我希望它会有所帮助。

I modified Jitendra's answer in Kotlin:我在 Kotlin 中修改了 Jitendra 的回答:

fun getDaysBetweenDates(firstDateValue: String, secondDateValue: String, format: String): String
{
    val sdf = SimpleDateFormat(format, Locale.getDefault())

    val firstDate = sdf.parse(firstDateValue)
    val secondDate = sdf.parse(secondDateValue)

    if (firstDate == null || secondDate == null)
        return 0.toString()

    return (((secondDate.time - firstDate.time) / (1000 * 60 * 60 * 24)) + 1).toString()
}

and call it like并称之为

val days = getDaysBetweenDates("31-03-2020", "24-04-2020","dd-MM-yyyy")

SUPER SIMPLE超级简单

use LocalDate() include implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1' to use in android使用LocalDate()包含implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'以在 android 中使用

Example例子

IN KOTLIN在科特林

val daysDifferene = LocalDate.of(2017,3,3).toEpochDay() - LocalDate.of(2017,3,2)

even better甚至更好

create extension function to LocalDate classLocalDate类创建扩展函数

private operator fun LocalDate.minus(other: LocalDate) = toEpochDay() - other.toEpochDay()
  

now just say现在就说

val daysDifference = localDate1 - localDate2 // you get number of days in Long type

IN JAVA在爪哇

long daysDifference = LocalDate.of(2017,3,3).toEpochDay() - LocalDate.of(2107,3,2) 

You can use joda time, it so simple你可以使用joda time,就这么简单

fun getBetweenDates(startDate: Long, endDate: Long): String {
    val period = Period(startDate, endDate, PeriodType.yearMonthDayTime())

    val formatter = PeriodFormatterBuilder()
        .appendYears().appendSuffix(" year ")
        .appendMonths().appendSuffix(" month ")
        .appendDays().appendSuffix(" days ")
        .appendHours().appendSuffix(" hours ")
        .appendMinutes().appendSuffix(" minutes ")
        .appendSeconds().appendSuffix(" seconds ")
        .appendMillis().appendSuffix(" millis ")
        .toFormatter()

    return formatter.print(period)
}

start and end dates millisecond, and result example: "2 year 1 month ..."开始和结束日期毫秒,结果示例:“2 年 1 月 ...”

fun countDaysBetweenTwoCalendar(calendarStart: Calendar, calendarEnd: Calendar) : Int{
    val millionSeconds = calendarEnd.timeInMillis - calendarStart.timeInMillis
    val days = TimeUnit.MILLISECONDS.toDays(millionSeconds) //this way not round number
    val daysRounded = (millionSeconds / (1000.0 * 60 * 60 * 24)).roundToInt()
    return daysRounded
}

while none of these worked for me, here is an easy way to implement your code with a very simple fonction :虽然这些都不适合我,但这是一种使用非常简单的函数来实现代码的简单方法:

private long getDaysDifference(Date fromDate,Date toDate) {

    if(fromDate == null || toDate == null)
        return 0;


    int a = Integer.parseInt(DateFormat.format("dd",   fromDate)+"");
    int b = Integer.parseInt(DateFormat.format("dd",   toDate)+"");

    if ( b <= a){
        return Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH) + b - a;
    }
    return b - a;
}

EnJoY请享用

use this way :使用这种方式:

 fun stringDateToCalendar(dateString: String?, formatString: String): Calendar? {

        if (dateString == null || dateString.isEmpty() || formatString.isBlank())
            return null

        val inputDateFormat = SimpleDateFormat(formatString, Locale.ENGLISH)

        return try {
            inputDateFormat.parse(dateString)?.let {
                val cal = Calendar.getInstance()
                cal.time = it
                cal
            }
        } catch (e: ParseException) {
            null
        }

 }
    
 val calendarFrom = stringDateToCalendar(
      "2021-12-12",
      "yyyy-MM-dd"
 )

 val calendarTo = CalendarUtils.stringDateToCalendar(
      "2022-03-20",
      "yyyy-MM-dd"
 )
    
    

 val msDiff = calendarTo?.timeInMillis?.minus(calendarFrom?.timeInMillis ?: 0) ?: 0
 val daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff)

Here the simply common function Kotlin code这里简单常见的 function Kotlin 代码

Here comparing these formatted dates "2022-11-04", "2022-11-20" Output will be 16 Days这里比较这些格式化日期“2022-11-04”,“2022-11-20” Output 将是16 天

 open fun dateSubstraction(date1: String, date2: String): String {
        val dateFormatter = SimpleDateFormat("yyyy-MM-dd") //Define input date format here
        val formatedDate1= dateFormat.parse(date1)  //formated  date1
        val formatedDate2= dateFormat.parse(date2)  //formated date2
        val millionSeconds = formatedDate2.time - formatedDate1.time
        return TimeUnit.MILLISECONDS.toDays(millionSeconds).toString()+"Days"
    }

I have done this work in past.我过去做过这项工作。 This was very simple这很简单

 val currentCalendar = Calendar.getInstance()
    val targetCalendar = Calendar.getInstance().apply {
        set(2023, Calendar.APRIL, 9, 23, 59, 59)
    }//your input: date, month, and time
    val difference = targetCalendar.timeInMillis - currentCalendar.timeInMillis
    val differenceInDays = TimeUnit.MILLISECONDS.toDays(difference)
    val remainingMonths = differenceInDays / 30//remaining months
    val remainingDays = differenceInDays % 30//remaining days
    val differenceInSeconds = TimeUnit.MILLISECONDS.toSeconds(difference)
    val differenceInMinutes = TimeUnit.MILLISECONDS.toMinutes(difference)
    val differenceInHours = TimeUnit.MILLISECONDS.toHours(difference)
    val remainingSeconds = differenceInSeconds % 60//remaining seconds
    val remainingMinutes = differenceInMinutes % 60//remaining minutes
    val remainingHours = differenceInHours % 24// remaining hours

Thats It We have done it就是这样 我们已经做到了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM