Android / Java - разница в днях - PullRequest
75 голосов
/ 01 октября 2010

Я получаю текущую дату (в формате 31.12.1999, т.е. мм / дд / гггг), используя следующий код:

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

, и у меня есть другая дата в формате: 2010-08-25 (т.е. гггг / мм / дд), * ​​1004 *

, поэтому я хочу найти разницу между датой в количестве дней, как мне найти разницу в днях?

(Другими словами, я хочу найти разницу между ТЕКУЩАЯ ДАТА - дата в формате гггг / мм / дд )

Ответы [ 18 ]

123 голосов
/ 01 октября 2010

Не совсем надежный метод, лучше использовать 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

Вот приблизительное значение ...

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

Для анализа даты из строки, вы можете использовать

  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....

Хотя, так как вы уверены в формате даты ... Вы также можете сделать Integer.parseInt() для его подстрок, чтобы получить их числовые значения.

80 голосов
/ 20 июня 2011

Это НЕ моя работа, нашел ответ здесь .не хотел в будущем неработающей ссылки:).

Ключом является эта строка для учета настроек дневного света, ref Full Code.

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

или попробуйте передать TimeZone какпараметр daysBetween() и вызов setTimeZone() в объектах sDate и eDate.

Итак, вот так:

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 () взято из здесь

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

Нюансы: Найти разницу между двумя датами не так просто, как вычитание двух дат и деление результата на (24 * 60 * 60 * 1000).Infact, его ошибочный!

Например: Разница между двумя датами 24.03.2007 и 25.03.2007 должна составлять 1 день;Однако, используя вышеуказанный метод, в Великобритании вы получите 0 дней!

Убедитесь сами (код ниже).Переход на миллисекунды приведет к округлению ошибок, и они станут наиболее очевидными, когда на снимке появится такая мелочь, как летнее время.

Полный код:

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) {
  ...
}

ВЫХОД:

Вручную - Дни с 1 января 2007 года по 2 января 2007 года: 1

Календарь - Дни между: 01 января 2007 года и 02 января 2007 года: 1


Руководство - Дни между 24 марта 2007 года и 25 марта 2007 года: 0

Календарь - Дни между 24 марта 2007 года и 25 марта 2007 года: 1

36 голосов
/ 29 сентября 2013

Большинство ответов были хорошими и подходящими для вашей проблемы

, поэтому я хочу найти разницу между датой в количестве дней, как мне найти разницу в днях?

Я предлагаю этот очень простой и понятный подход, который гарантированно даст вам правильную разницу в любом часовом поясе:

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

И все!

24 голосов
/ 01 октября 2010

Используйте jodatime API

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

, где 'start' и 'end' - это ваши DateTime объекты.Чтобы проанализировать ваши строки Date в объектах DateTime, используйте метод parseDateTime

Существует также специфичная для Android библиотека JodaTime .

14 голосов
/ 22 февраля 2012

Этот фрагмент учитывает переход на летнее время и имеет значение 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));
}
6 голосов
/ 11 октября 2013

Это простой и лучший расчет для меня и может быть для вас.

       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);
        }
3 голосов
/ 27 июня 2016

tl; dr

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

Подробности

Другие ответы устарели.Старые классы даты и времени, включенные в ранние версии Java, оказались плохо спроектированными, запутанными и хлопотными.Избегайте их.

java.time

Проект Joda-Time был весьма успешным в качестве замены для этих старых классов.Эти классы послужили источником вдохновения для java.time фреймворка, встроенного в Java 8 и более поздние версии.

Большая часть функций java.time перенесена в Java 6 & 7 в ThreeTen-Backport и дополнительно адаптирована для Android в ThreeTenABP .

LocalDate

Класс LocalDate представляет значение только для даты без времени суток и без часового пояса.

Разбор строк

Если ваши входные строки имеют стандартный формат ISO 8601 , класс LocalDate может непосредственно анализировать строку.

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

Если не в формате ISO 8601, определите шаблон форматирования с помощью DateTimeFormatter.

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

Прошедших дней через ChronoUnit

Теперь получите счетдней, прошедших между этой парой LocalDate объектов.Перечисление ChronoUnit вычисляет истекшее время.

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

Если вы не знакомы с перечислениями Java, знайте, что они гораздо более мощные и полезные, чем обычные перечисления в большинстве других языков программирования.См. Enum учебный документ, Oracle Tutorial и Wikipedia , чтобы узнать больше.


О java.time

Фреймворк java.time встроен в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

Где получить классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и more .

3 голосов
/ 31 января 2012

Correct Way из ответа Сэма Квеста работает, только если первая дата раньше, чем вторая.Более того, он вернет 1, если две даты находятся в пределах одного дня.

Это решение, которое лучше всего сработало для меня.Как и большинство других решений, он по-прежнему будет показывать неверные результаты в течение двух дней в году из-за неправильного смещения для экономии дневного света.

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);
}
3 голосов
/ 04 февраля 2016

лучший и самый простой способ сделать это

  public int getDays(String begin) throws ParseException {
     long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
     SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);

    long begin = dateFormat.parse(begin).getTime();
    long end = new Date().getTime(); // 2nd date want to compare
    long diff = (end - begin) / (MILLIS_PER_DAY);
    return (int) diff;
}
2 голосов
/ 26 января 2015

Все эти решения страдают одной из двух проблем. Либо решение не совсем точное из-за ошибок округления, високосных дней и секунд и т. Д., Либо вы в конечном итоге зацикливаетесь на количество дней между двумя вашими неизвестными датами.

Это решение решает первую проблему и улучшает вторую примерно в 365 раз, лучше, если вы знаете, каков ваш максимальный диапазон.

/**
 * @param thisDate
 * @param thatDate
 * @param maxDays
 *            set to -1 to not set a max
 * @returns number of days covered between thisDate and thatDate, inclusive, i.e., counting both
 *          thisDate and thatDate as an entire day. Will short out if the number of days exceeds
 *          or meets maxDays
 */
public static int daysCoveredByDates(Date thisDate, Date thatDate, int maxDays) {
    //Check inputs
    if (thisDate == null || thatDate == null) {
        return -1;
    }

    //Set calendar objects
    Calendar startCal = Calendar.getInstance();
    Calendar endCal = Calendar.getInstance();
    if (thisDate.before(thatDate)) {
        startCal.setTime(thisDate);
        endCal.setTime(thatDate);
    }
    else {
        startCal.setTime(thatDate);
        endCal.setTime(thisDate);
    }

    //Get years and dates of our times.
    int startYear = startCal.get(Calendar.YEAR);
    int endYear = endCal.get(Calendar.YEAR);
    int startDay = startCal.get(Calendar.DAY_OF_YEAR);
    int endDay = endCal.get(Calendar.DAY_OF_YEAR);

    //Calculate the number of days between dates.  Add up each year going by until we catch up to endDate.
    while (startYear < endYear && maxDays >= 0 && endDay - startDay + 1 < maxDays) {
        endDay += startCal.getActualMaximum(Calendar.DAY_OF_YEAR); //adds the number of days in the year startDate is currently in
        ++startYear;
        startCal.set(Calendar.YEAR, startYear); //reup the year
    }
    int days = endDay - startDay + 1;

    //Honor the maximum, if set
    if (maxDays >= 0) {
        days = Math.min(days, maxDays);
    }
    return days;
}

Если вам нужны дни между датами (не считая последней даты), просто избавьтесь от + 1, когда увидите endDay - startDay + 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...