【问题标题】:Android calculate days between two datesAndroid计算两个日期之间的天数
【发布时间】:2017-07-22 00:53:15
【问题描述】:

我编写了以下代码来查找两个日期之间的天数

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

当开始日期和结束日期分别为 2/3/2017 和 3/3/2017 时,显示的天数为 29。虽然它们是同一天,但显示为 1。(天数需要一个请假。所以如果一个人请一天假,他必须选择相同的开始和结束日期。所以在这种情况下,他请了两天假。

我做错了什么? 感谢您的宝贵时间。

注意:请不要使用日期构造函数。检查下面接受的答案。使用 simpledateformat 或 Joda 时间。日期构造函数已弃用。

【问题讨论】:

  • startDateendDate 到底是什么? (我们目前甚至不知道他们的类型。)如果您可以改用 Joda Time,那会更好很多,顺便说一句。
  • @JonSkeet startDate = (string)2/3/2017 endDate = (string)3/3/2017
  • 所以您使用的是已弃用的Date(String) 构造函数?我会停止这样做,开始。我建议使用具有特定格式的 SimpleDateFormat 并使用 UTC 时区。 (很可能由于 DST 转换,您得到了错误的结果 - 如果不知道您所在的时区,就很难知道。)
  • 很高兴听到这个消息。该构造函数在 20 多年前已被弃用:)
  • 仅供参考,麻烦的旧日期时间类,如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 和 Java 9 中内置的 java.time 类所取代. 见Tutorial by Oracle请参阅modern Answer by Anton Balaniuc

标签: java android date datetime kotlin


【解决方案1】:

您生成日期对象的代码:

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

您得到 28 天作为答案,因为根据 Date(String) 构造函数,它认为 day = 3,month = 2 和 year = 2017

您可以将字符串转换为日期,如下所示:

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

使用上面的模板来制作你的 Date 对象。然后使用下面的代码计算两个日期之间的天数。希望这能解决问题。

可以这样做:

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

请查看link

如果你使用 Joda Time,那就简单多了:

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

请查看JodaTime

How to use JodaTime in Java Project

【讨论】:

  • 2/3/2017,3/3/2017 仍然显示 28 天。等待使用 joda 时间并通知您
  • 请问startDateendDate 变量的值是多少?
  • startDate = (string)2/3/2017 endDate = (string)3/3/2017
  • 不推荐使用此方法,最好使用 SimpleDateFormat。您只想继续使用此代码吗?你可以在这里查看docs.oracle.com/javase/7/docs/api/java/util/Date.html
  • 好的,那么我将尝试使用 SimpleDateFormat。但稍后。现在我想尽快更正此问题
【解决方案2】:
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));
}

【讨论】:

    【解决方案3】:

    Android 是否完全支持java-8?如果是,您可以简单地使用ChronoUnit class

    LocalDate start = LocalDate.of(2017,2,3);
    LocalDate end = LocalDate.of(2017,3,3);
    
    System.out.println(ChronoUnit.DAYS.between(start, end)); // 28
    

    或使用格式化程序做同样的事情

    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
    

    【讨论】:

    【解决方案4】:

    您使用什么日期格式?是d/M/yyyy 还是M/d/yyyy

    d = 日,M = 月,yyyy = 年

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

    然后是代码:

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

    对于getUnitBetweenDates 方法:

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

    【讨论】:

      【解决方案5】:

      看看这段代码,这对我有帮助,希望对你有帮助。

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

      }

      【讨论】:

      • 谢谢我尝试了这个代码,这是有效的。我赞成它,但我接受了最简单的答案。无论如何感谢您的时间
      • 我喜欢老式的方法。也许冗长,也许其他人会皱眉……但至少它适用于任何地方,无论新旧。非常感谢。
      【解决方案6】:

      非常简单,只需使用日历,为两个日期创建两个实例,转换为毫秒,减去并转换为天数(四舍五入)......基本上是这样的:

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

      【讨论】:

        【解决方案7】:

        如果您想使用收到的整数,请小心,例如在自定义日历实现中指示特定日期。例如,我尝试在 m 应用程序中从月历视图进入每日视图并显示每日内容,通过计算从 1970-01-01 到选定的日期,每个月的 25-31 天显示我提前一天,因为datesDifferenceInMillis / (24 * 60 * 60 * 1000); 可能会返回类似 17645,95833333333 的内容,然后将其转换为 int,您将获得低 1 的值。在这种情况下,您将通过使用 NumberFormat 类对接收到的浮点数进行四舍五入,从而获得正确的天数。这是我的代码:

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

        希望对你有所帮助。

        【讨论】:

        • 天并不总是 24 小时,所以这不准确。更容易使用ChronoUnit.DAYS.between( start , stop )
        【解决方案8】:

        科特林

        这是计算从今天到某个日期的天数的示例:

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

        如果要计算两天,那就改:

        val millionSeconds = yourDate1.time - yourDate2.time
        

        应该可以。

        【讨论】:

        • val millionSeconds = Calendar.getInstance().timeInMillis - yourDate.time
        【解决方案9】:

        我在 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()
        }
        

        然后这样称呼它

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

        【讨论】:

        【解决方案10】:

        java.time 和 ThreeTenABP

        如果我理解正确,您需要从开始日期到结束日期的天数包含

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

        输出:

        天数:2

        ChronoUnit.DAYS.between() 为我们提供从开始日期到结束日期的天数不包括。因此,要包括结束日期,我们需要添加 1 天,就像您在问题中所做的那样。

        你的代码出了什么问题?

        您正在使用Date(String) 构造函数。此构造函数自 1997 年以来已被弃用,因为它跨时区工作不可靠,所以不要使用它。这也有点神奇:至少我从来不知道我得到了什么。显然,2/3/2017 表示 2017 年 2 月 3 日,您打算在 2017 年 3 月 2 日。从 2 月 3 日到 3 月 3 日(含)是 29 天(因为 2017 年不是闰年)。这解释了为什么你得到 29。(如果有必要,我们可以通过文档拼写我们的方式,并找出为什么 2/3/2017 会被这样解释,只是我发现这样做毫无意义浪费时间。)

        您无法从毫秒转换。还请注意,不仅问题,而且从毫秒转换为天的很多答案都是不正确的。这种转换假设一天总是 24 小时。由于夏令时 (DST) 和其他时间异常,一天并不总是 24 小时。所有这些答案都太少了一天,例如,如果假期跨过了春季间隙春季开始,当夏季开始时。

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

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

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

        链接

        【讨论】:

          【解决方案11】:

          你可以使用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)
          }
          

          开始和结束日期毫秒,结果示例:“2 year 1 month ...”

          【讨论】:

            【解决方案12】:
            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
            }
            

            【讨论】:

            • 欢迎来到 StackOverflow!请提供解释,以改进您的答案并让社区更容易理解
            【解决方案13】:

            虽然这些都不适合我,但这里有一个简单的方法来用一个非常简单的函数来实现你的代码:

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

            尽情享受

            【讨论】:

              【解决方案14】:

              超级简单

              使用LocalDate() 包含implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1' 在android 中使用

              示例

              在科特林

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

              更好

              LocalDate类创建扩展函数

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

              现在就说

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

              在 JAVA 中

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

              【讨论】:

                【解决方案15】:

                这样使用:

                 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)
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-02-26
                  • 2019-09-27
                  • 1970-01-01
                  • 2011-11-08
                  相关资源
                  最近更新 更多