Android / Java – Diferencia de fechas en días

Estoy obteniendo la fecha actual (en formato 12/31/1999 es decir, mm / dd / aaaa) usando el siguiente código:

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

y estoy teniendo otra fecha en formato como: 2010-08-25 (es decir, aaaa / mm / dd),

entonces quiero encontrar la diferencia entre la fecha en cantidad de días, ¿cómo encuentro la diferencia en días?

(En otras palabras, quiero encontrar la diferencia entre la FECHA ACTUAL – fecha de formato aaaa / mm / dd )

Realmente no es un método confiable, mejor de usar 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 

Aquí hay una aproximación …

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

Para analizar la fecha desde una cadena, puede usar

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

Aunque, como está seguro del formato de fecha … También puede hacer que Integer.parseInt() en sus subcadenas obtenga sus valores numéricos.

Este no es mi trabajo, encontré la respuesta aquí . no quería un enlace roto en el futuro :).

La clave es esta línea para tener en cuenta la configuración de luz diurna, ref Full Code.

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

o intente pasar TimeZone como parámetro a daysBetween() y llame a setTimeZone() en los objetos sDate y eDate .

Así que aquí va:

 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 () tomado de aquí

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

Los matices: Encontrar la diferencia entre dos fechas no es tan sencillo como restar las dos fechas y dividir el resultado entre (24 * 60 * 60 * 1000). De hecho, es erróneo!

Por ejemplo: la diferencia entre las dos fechas 24/03/2007 y 25/03/2007 debe ser de 1 día; Sin embargo, utilizando el método anterior, en el Reino Unido, ¡obtendrás 0 días!

Véalo usted mismo (código a continuación). Avanzar milisegundos conducirá a redondear los errores y se harán más evidentes una vez que tengas algo como el horario de verano.

Código completo:

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

SALIDA:

Manual – Los días entre: 01-ene-2007 y 02-ene-2007 es: 1

Calendario – Los días entre: 01-ene-2007 y 02-ene-2007 es: 1


Manual – Los días entre: 24-mar-2007 y 25-mar-2007 es: 0

Calendario – Los días entre: 24-mar-2007 y 25-mar-2007 es: 1

La mayoría de las respuestas fueron buenas y correctas para su problema de

entonces quiero encontrar la diferencia entre la fecha en cantidad de días, ¿cómo encuentro la diferencia en días?

Sugiero este enfoque simple y directo que garantiza la diferencia correcta en cualquier zona horaria:

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

¡Y eso es!

Use la API jodatime

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

donde ‘inicio’ y ‘final’ son sus objetos DateTime . Para analizar las cadenas de fechas en objetos DateTime, utilice el método parseDateTime

También hay una biblioteca JodaTime específica de Android .

Este fragmento representa el horario de verano y es 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)); } 

Esto es simple y el mejor cálculo para mí y puede ser para usted.

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

La forma Correct Way de la respuesta de Sam Quest solo funciona si la primera fecha es anterior a la segunda. Además, devolverá 1 si las dos fechas están dentro de un solo día.

Esta es la solución que mejor funcionó para mí. Al igual que la mayoría de las otras soluciones, aún mostraría resultados incorrectos en dos días en un año debido a una compensación de ahorro de luz diurna incorrecta.

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

mejor y más fácil manera de hacer esto

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

Use las siguientes funciones:

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

Hay una solución simple, que al menos para mí es la única solución viable.

El problema es que todas las respuestas que veo que se arrojan (usando Joda, o Calendario, o Fecha, o lo que sea) solo toman en consideración la cantidad de milisegundos. Terminan contando el número de ciclos de 24 horas entre dos fechas , en lugar de la cantidad real de días . Así que algo del 1 de enero a las 11 p.m. al 2 de enero a la 1 a.m. devolverá 0 días.

Para contar el número real de días entre startDate y endDate , simplemente haga:

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

Esto devolverá “1” entre el 2 de enero y el 1 de enero. Si necesita contar el día final, solo agregue 1 a daysBetween (tuve que hacer eso en mi código porque quería contar el número total de días en el rango).

Esto es algo similar a lo que Daniel ha sugerido, pero supongo que es un código más pequeño.

Todas estas soluciones sufren de uno de dos problemas. O bien la solución no es perfectamente precisa debido a errores de redondeo, días bisiestos y segundos, etc. o puede terminar recorriendo el número de días entre sus dos fechas desconocidas.

Esta solución resuelve el primer problema, y ​​mejora el segundo en un factor de aproximadamente 365, mejor si sabes cuál es tu rango máximo.

 /** * @param thisDate * @param thatDate * @param maxDays * set to -1 to not set a max * @returns number of days covered between thisDate and thatDate, inclusive, ie, 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; } 

Si necesita días entre fechas (sin incluir la última fecha), simplemente deshágase del + 1 cuando vea endDay - startDay + 1 .

tl; dr

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

Detalles

Otras respuestas están desactualizadas. Las antiguas clases de fecha y hora incluidas con las primeras versiones de Java han demostrado ser mal diseñadas, confusas y problemáticas. Evítales.

java.time

El proyecto Joda-Time fue un gran éxito como reemplazo de esas antiguas clases. Estas clases proporcionaron la inspiración para el marco java.time integrado en Java 8 y posterior.

Gran parte de la funcionalidad de java.time se transfiere a Java 6 y 7 en ThreeTen-Backport y se adapta aún más a Android en ThreeTenABP .

LocalDate

La clase LocalDate representa un valor de solo fecha sin hora del día y sin zona horaria.

Análisis de cadenas

Si sus cadenas de entrada están en formato estándar ISO 8601 , la clase LocalDate puede analizar directamente la cadena.

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

Si no está en formato ISO 8601, defina un patrón de formato con DateTimeFormatter .

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

Días transcurridos a través de ChronoUnit

Ahora obtenga un recuento de los días transcurridos entre ese par de objetos LocalDate . ChronoUnit enum calcula el tiempo transcurrido.

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

Si no está familiarizado con las enumeraciones de Java, sepa que son mucho más poderosas y útiles que las enumeraciones convencionales en la mayoría de los otros lenguajes de progtwigción. Consulte el documento de la clase Enum , el Tutorial de Oracle y Wikipedia para obtener más información.


Acerca de java.time

El marco java.time está integrado en Java 8 y posterior. Estas clases suplantan a las problemáticas antiguas clases heredadas de fecha y hora como java.util.Date , Calendar y SimpleDateFormat .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

¿Dónde obtener las clases de java.time?

  • Java SE 8 y SE 9 y posteriores
    • Incorporado.
    • Parte de la API Java estándar con una implementación integrada.
    • Java 9 agrega algunas características y correcciones menores.
  • Java SE 6 y SE 7
    • Gran parte de la funcionalidad de java.time se transfiere a Java 6 y 7 en ThreeTen-Backport .
  • Androide
    • El proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente) específicamente para Android.
    • Consulte Cómo utilizar ThreeTenABP ….

El proyecto ThreeTen-Extra amplía java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval , YearWeek , YearQuarter y más .

De otra manera:

 public static int numberOfDaysBetweenDates(Calendar fromDay, Calendar toDay) { fromDay = calendarStartOfDay(fromDay); toDay = calendarStartOfDay(toDay); long from = fromDay.getTimeInMillis(); long to = toDay.getTimeInMillis(); return (int) TimeUnit.MILLISECONDS.toDays(to - from); } 

Encontré una manera muy fácil de hacer esto y es lo que estoy usando en mi aplicación.

Digamos que tiene las fechas en objetos Time (o lo que sea, solo necesitamos los milisegundos):

 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 } 

Joda-Time

La mejor manera es utilizar Joda-Time , la biblioteca de código abierto de gran éxito que agregaría a su proyecto.

 String date1 = "2015-11-11"; String date2 = "2013-11-11"; DateTimeFormatter formatter = new DateTimeFormat.forPattern("yyyy-MM-dd"); DateTime d1 = formatter.parseDateTime(date1); DateTime d2 = formatter.parseDateTime(date2); long diffInMillis = d2.getMillis() - d1.getMillis(); Duration duration = new Duration(d1, d2); int days = duration.getStandardDays(); int hours = duration.getStandardHours(); int minutes = duration.getStandardMinutes(); 

Si usa Android Studio , es muy fácil agregar joda-time. En su build.gradle (aplicación):

 dependencies { compile 'joda-time:joda-time:2.4' compile 'joda-time:joda-time:2.4' compile 'joda-time:joda-time:2.2' } 
  Date userDob = new SimpleDateFormat("yyyy-MM-dd").parse(dob); Date today = new Date(); long diff = today.getTime() - userDob.getTime(); 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)); 

usa estas funciones

  public static int getDateDifference(int previousYear, int previousMonthOfYear, int previousDayOfMonth, int nextYear, int nextMonthOfYear, int nextDayOfMonth, int differenceToCount){ // int differenceToCount = can be any of the following // Calendar.MILLISECOND; // Calendar.SECOND; // Calendar.MINUTE; // Calendar.HOUR; // Calendar.DAY_OF_MONTH; // Calendar.MONTH; // Calendar.YEAR; // Calendar.---- Calendar previousDate = Calendar.getInstance(); previousDate.set(Calendar.DAY_OF_MONTH, previousDayOfMonth); // month is zero indexed so month should be minus 1 previousDate.set(Calendar.MONTH, previousMonthOfYear); previousDate.set(Calendar.YEAR, previousYear); Calendar nextDate = Calendar.getInstance(); nextDate.set(Calendar.DAY_OF_MONTH, previousDayOfMonth); // month is zero indexed so month should be minus 1 nextDate.set(Calendar.MONTH, previousMonthOfYear); nextDate.set(Calendar.YEAR, previousYear); return getDateDifference(previousDate,nextDate,differenceToCount); } public static int getDateDifference(Calendar previousDate,Calendar nextDate,int differenceToCount){ // int differenceToCount = can be any of the following // Calendar.MILLISECOND; // Calendar.SECOND; // Calendar.MINUTE; // Calendar.HOUR; // Calendar.DAY_OF_MONTH; // Calendar.MONTH; // Calendar.YEAR; // Calendar.---- //raise an exception if previous is greater than nextdate. if(previousDate.compareTo(nextDate)>0){ throw new RuntimeException("Previous Date is later than Nextdate"); } int difference=0; while(previousDate.compareTo(nextDate)<=0){ difference++; previousDate.add(differenceToCount,1); } return difference; }