una sumar saber restar rango para milisegundos meses fechas fecha faltan entre dias cuantos convertir comparar calcular años java jodatime datediff

sumar - saber cuantos dias faltan para una fecha java



¿Diferencia en días entre dos fechas en Java? (20)

Necesito encontrar el número de días entre dos fechas : una es de un informe y la otra es la fecha actual. Mi fragmento:

int age=calculateDifference(agingDate, today);

Aquí calculateDifference es un método privado, agingDate y today son objetos Date , solo para su aclaración. He seguido dos artículos de un foro de Java, Subproceso 1 / Subproceso 2 .

Funciona bien en un programa independiente, aunque cuando incluyo esto en mi lógica para leer del informe obtengo una diferencia inusual en los valores.

¿Por qué está sucediendo y cómo puedo solucionarlo?

EDITAR:

Recibo una mayor cantidad de días en comparación con la cantidad real de días.

public static int calculateDifference(Date a, Date b) { int tempDifference = 0; int difference = 0; Calendar earlier = Calendar.getInstance(); Calendar later = Calendar.getInstance(); if (a.compareTo(b) < 0) { earlier.setTime(a); later.setTime(b); } else { earlier.setTime(b); later.setTime(a); } while (earlier.get(Calendar.YEAR) != later.get(Calendar.YEAR)) { tempDifference = 365 * (later.get(Calendar.YEAR) - earlier.get(Calendar.YEAR)); difference += tempDifference; earlier.add(Calendar.DAY_OF_YEAR, tempDifference); } if (earlier.get(Calendar.DAY_OF_YEAR) != later.get(Calendar.DAY_OF_YEAR)) { tempDifference = later.get(Calendar.DAY_OF_YEAR) - earlier.get(Calendar.DAY_OF_YEAR); difference += tempDifference; earlier.add(Calendar.DAY_OF_YEAR, tempDifference); } return difference; }

Nota :

Desafortunadamente, ninguna de las respuestas me ayudó a resolver el problema. Logré este problema con la ayuda de la biblioteca Joda-time .


ThreeTen-Extra

La respuesta de Vitalii Fedorenko es correcta, describiendo cómo realizar este cálculo de una manera moderna con java.time clases java.time ( Duration & ChronoUnit ) integradas en Java 8 y posterior (y back-ported a Java 6 y 7 y a Android ).

Days

Si usa un número de días rutinariamente en su código, puede reemplazar números enteros con el uso de una clase. La clase Days se puede encontrar en el proyecto ThreeTen-Extra , una extensión de java.time y campo de pruebas para posibles adiciones futuras a java.time. La clase Days proporciona una forma segura de tipo de representar un número de días en su aplicación. La clase incluye constantes convenientes para ZERO y ONE .

Dado los viejos objetos obsoletos java.util.Date en la Pregunta, primero java.time.Instant modernos objetos java.time.Instant . Las antiguas clases de fecha y hora tienen métodos recientemente agregados para facilitar la conversión a java.time, como java.util.Date::toInstant .

Instant start = utilDateStart.toInstant(); // Inclusive. Instant stop = utilDateStop.toInstant(); // Exclusive.

Pase ambos objetos Instant al método de fábrica para Days .

En la implementación actual (2016-06), este es un contenedor que llama a java.time.temporal.ChronoUnit.DAYS.between , lea el ChronoUnit clase ChronoUnit para obtener más información. Para que quede claro: todos los DAYS mayúsculas están en la enumeración ChronoUnit mientras que ChronoUnit -cap Days es una clase de ThreeTen-Extra.

Days days = Days.between( start , stop );

Puede pasar estos objetos Days alrededor de su propio código. Puede serializar a una Cadena en el formato estándar ISO 8601 llamando a String. Este formato de PnD usa una P para marcar el comienzo y D significa "días", con un número de días intermedios. Tanto las clases java.time como ThreeTen-Extra usan estos formatos estándar de forma predeterminada al generar y analizar Cadenas que representan valores de fecha y hora.

String output = days.toString();

P3D

Days days = Days.parse( "P3D" );


java.time

En Java 8 y posterior, use el java.time ( Tutorial ).

Duration

La clase de Duration representa un lapso de tiempo como una cantidad de segundos más una fracción de segundo. Puede contar días, horas, minutos y segundos.

ZonedDateTime now = ZonedDateTime.now(); ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10); Duration duration = Duration.between(oldDate, now); System.out.println(duration.toDays());

ChronoUnit

Si todo lo que necesita es el número de días, alternativamente puede usar la enum ChronoUnit . Observe que los métodos de cálculo devuelven una long que int .

long days = ChronoUnit.DAYS.between( then, now );


¿Cien líneas de código para esta función básica?

Solo un método simple:

protected static int calculateDayDifference(Date dateAfter, Date dateBefore){ return (int)(dateAfter.getTime()-dateBefore.getTime())/(1000 * 60 * 60 * 24); // MILLIS_IN_DAY = 1000 * 60 * 60 * 24; }


Basado en la respuesta de @ Mad_Troll, desarrollé este método.

He ejecutado alrededor de 30 casos de prueba en su contra, es el único método que maneja correctamente los fragmentos de horas del día.

Ejemplo: si pasa ahora y ahora + 1 milisegundo, ese es el mismo día. Hacer 1-1-13 23:59:59.098 a 1-1-13 23:59:59.099 devuelve 0 días, correctamente; La asignación de los otros métodos publicados aquí no hará esto correctamente.

Vale la pena señalar que no le importa de qué manera los ingresa. Si su fecha de finalización es anterior a su fecha de inicio, contará hacia atrás.

/** * This is not quick but if only doing a few days backwards/forwards then it is very accurate. * * @param startDate from * @param endDate to * @return day count between the two dates, this can be negative if startDate is after endDate */ public static long daysBetween(@NotNull final Calendar startDate, @NotNull final Calendar endDate) { //Forwards or backwards? final boolean forward = startDate.before(endDate); // Which direction are we going final int multiplier = forward ? 1 : -1; // The date we are going to move. final Calendar date = (Calendar) startDate.clone(); // Result long daysBetween = 0; // Start at millis (then bump up until we go back a day) int fieldAccuracy = 4; int field; int dayBefore, dayAfter; while (forward && date.before(endDate) || !forward && endDate.before(date)) { // We start moving slowly if no change then we decrease accuracy. switch (fieldAccuracy) { case 4: field = Calendar.MILLISECOND; break; case 3: field = Calendar.SECOND; break; case 2: field = Calendar.MINUTE; break; case 1: field = Calendar.HOUR_OF_DAY; break; default: case 0: field = Calendar.DAY_OF_MONTH; break; } // Get the day before we move the time, Change, then get the day after. dayBefore = date.get(Calendar.DAY_OF_MONTH); date.add(field, multiplier); dayAfter = date.get(Calendar.DAY_OF_MONTH); // This shifts lining up the dates, one field at a time. if (dayBefore == dayAfter && date.get(field) == endDate.get(field)) fieldAccuracy--; // If day has changed after moving at any accuracy level we bump the day counter. if (dayBefore != dayAfter) { daysBetween += multiplier; } } return daysBetween; }

Puede eliminar las anotaciones @NotNull , estas son usadas por Intellij para hacer análisis de código sobre la marcha


Debe usar la biblioteca Joda Time porque Java Util Date devuelve a veces valores incorrectos.

Joda vs Java Util Fecha

Por ejemplo, días entre ayer (dd-mm-aaaa, 12-07-2016) y primer día del año en 1957 (dd-mm-aaa, 01-01-1957):

public class Main { public static void main(String[] args) { SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy"); Date date = null; try { date = format.parse("12-07-2016"); } catch (ParseException e) { e.printStackTrace(); } //Try with Joda - prints 21742 System.out.println("This is correct: " + getDaysBetweenDatesWithJodaFromYear1957(date)); //Try with Java util - prints 21741 System.out.println("This is not correct: " + getDaysBetweenDatesWithJavaUtilFromYear1957(date)); } private static int getDaysBetweenDatesWithJodaFromYear1957(Date date) { DateTime jodaDateTime = new DateTime(date); DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy"); DateTime y1957 = formatter.parseDateTime("01-01-1957"); return Days.daysBetween(y1957 , jodaDateTime).getDays(); } private static long getDaysBetweenDatesWithJavaUtilFromYear1957(Date date) { SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy"); Date y1957 = null; try { y1957 = format.parse("01-01-1957"); } catch (ParseException e) { e.printStackTrace(); } return TimeUnit.DAYS.convert(date.getTime() - y1957.getTime(), TimeUnit.MILLISECONDS); }

Así que realmente te aconsejo que uses la biblioteca Joda Time.


Depende de lo que defina como la diferencia. Para comparar dos fechas a la medianoche, puede hacerlo.

long day1 = ...; // in milliseconds. long day2 = ...; // in milliseconds. long days = (day2 - day1) / 86400000;


El diff / (24 * etc.) no tiene en cuenta la zona horaria, por lo que si su zona horaria predeterminada tiene un horario de verano, puede descartar el cálculo.

Este link tiene una implementación pequeña y agradable.

Aquí está la fuente del enlace de arriba en caso de que el enlace se caiga:

/** Using Calendar - THE CORRECT WAY**/ public static long daysBetween(Calendar startDate, Calendar endDate) { //assert: startDate must be before endDate Calendar date = (Calendar) startDate.clone(); long daysBetween = 0; while (date.before(endDate)) { date.add(Calendar.DAY_OF_MONTH, 1); daysBetween++; } return daysBetween; }

y

/** Using Calendar - THE CORRECT (& Faster) WAY**/ public static long daysBetween(final Calendar startDate, final Calendar endDate) { //assert: startDate must be before endDate int MILLIS_IN_DAY = 1000 * 60 * 60 * 24; long endInstant = endDate.getTimeInMillis(); int presumedDays = (int) ((endInstant - startDate.getTimeInMillis()) / MILLIS_IN_DAY); Calendar cursor = (Calendar) startDate.clone(); cursor.add(Calendar.DAY_OF_YEAR, presumedDays); long instant = cursor.getTimeInMillis(); if (instant == endInstant) return presumedDays; final int step = instant < endInstant ? 1 : -1; do { cursor.add(Calendar.DAY_OF_MONTH, step); presumedDays += step; } while (cursor.getTimeInMillis() != endInstant); return presumedDays; }


Este código calcula los días entre cadenas de 2 fechas:

static final long MILLI_SECONDS_IN_A_DAY = 1000 * 60 * 60 * 24; static final String DATE_FORMAT = "dd-MM-yyyy"; public long daysBetween(String fromDateStr, String toDateStr) throws ParseException { SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT); Date fromDate; Date toDate; fromDate = format.parse(fromDateStr); toDate = format.parse(toDateStr); return (toDate.getTime() - fromDate.getTime()) / MILLI_SECONDS_IN_A_DAY; }


Ilustración del problema: (Mi código está calculando delta en semanas, pero el mismo problema se aplica con delta en días)

Aquí hay una implementación de aspecto muy razonable:

public static final long MILLIS_PER_WEEK = 7L * 24L * 60L * 60L * 1000L; static public int getDeltaInWeeks(Date latterDate, Date earlierDate) { long deltaInMillis = latterDate.getTime() - earlierDate.getTime(); int deltaInWeeks = (int)(deltaInMillis / MILLIS_PER_WEEK); return deltaInWeeks; }

Pero esta prueba fallará:

public void testGetDeltaInWeeks() { delta = AggregatedData.getDeltaInWeeks(dateMar09, dateFeb23); assertEquals("weeks between Feb23 and Mar09", 2, delta); }

La razón es:

Lun Mar 09 00:00:00 EDT 2009 = 1,236,571,200,000
Lun Feb 23 00:00:00 EST 2009 = 1,235,365,200,000
MillisPerWeek = 604,800,000
Así,
(Mar09 - Feb23) / MillisPerWeek =
1,206,000,000 / 604,800,000 = 1.994 ...

pero cualquiera que mire un calendario estaría de acuerdo en que la respuesta es 2.


Lo hice de esta manera. es fácil :)

Date d1 = jDateChooserFrom.getDate(); Date d2 = jDateChooserTo.getDate(); Calendar day1 = Calendar.getInstance(); day1.setTime(d1); Calendar day2 = Calendar.getInstance(); day2.setTime(d2); int from = day1.get(Calendar.DAY_OF_YEAR); int to = day2.get(Calendar.DAY_OF_YEAR); int difference = to-from;



Puede que sea demasiado tarde para unirme al juego, pero qué diablos, ¿eh? :)

¿Crees que esto es un problema de enhebrado? ¿Cómo está utilizando el resultado de este método, por ejemplo? O

Podemos cambiar tu código para hacer algo tan simple como:

Calendar calendar1 = Calendar.getInstance(); Calendar calendar2 = Calendar.getInstance(); calendar1.set(<your earlier date>); calendar2.set(<your current date>); long milliseconds1 = calendar1.getTimeInMillis(); long milliseconds2 = calendar2.getTimeInMillis(); long diff = milliseconds2 - milliseconds1; long diffSeconds = diff / 1000; long diffMinutes = diff / (60 * 1000); long diffHours = diff / (60 * 60 * 1000); long diffDays = diff / (24 * 60 * 60 * 1000); System.out.println("/nThe Date Different Example"); System.out.println("Time in milliseconds: " + diff + " milliseconds."); System.out.println("Time in seconds: " + diffSeconds + " seconds."); System.out.println("Time in minutes: " + diffMinutes + " minutes."); System.out.println("Time in hours: " + diffHours + " hours."); System.out.println("Time in days: " + diffDays + " days."); }


Si está buscando una solución que devuelva el número o los días correctos, por ejemplo, entre el 11/30/2014 23:59 y el 12/01/2014 00:01 es la solución que utiliza Joda Time.

private int getDayDifference(long past, long current) { DateTime currentDate = new DateTime(current); DateTime pastDate = new DateTime(past); return currentDate.getDayOfYear() - pastDate.getDayOfYear(); }

Esta implementación devolverá 1 como una diferencia en días. La mayoría de las soluciones publicadas aquí calculan la diferencia en milisegundos entre dos fechas. Significa que se devolverá 0 porque solo hay 2 minutos de diferencia entre estas dos fechas.


Solución que usa la diferencia entre el tiempo de milisegundos, con el redondeo correcto para las fechas del horario de verano:

public static long daysDiff(Date from, Date to) { return daysDiff(from.getTime(), to.getTime()); } public static long daysDiff(long from, long to) { return Math.round( (to - from) / 86400000D ); // 1000 * 60 * 60 * 24 }

Una nota: por supuesto, las fechas deben estar en alguna zona horaria.

El código importante:

Math.round( (to - from) / 86400000D )

Si no desea una ronda, puede usar las fechas UTC,


Sugiero que uses la excelente biblioteca de Joda-Time lugar de la java.util.Date y sus amigos defectuosos. Simplemente puedes escribir

import java.util.Date; import org.joda.time.DateTime; import org.joda.time.Days; Date past = new Date(110, 5, 20); // June 20th, 2010 Date today = new Date(110, 6, 24); // July 24th int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays(); // => 34


Usted dice que "funciona bien en un programa independiente", pero que obtiene "valores de diferencia inusuales" cuando "incluye esto en mi lógica para leer del informe". Eso sugiere que su informe tiene algunos valores para los que no funciona correctamente, y su programa independiente no tiene esos valores. En lugar de un programa independiente, sugiero un caso de prueba. Escriba un caso de prueba como lo haría con un programa independiente, subclasificando desde la clase TestCase de JUnit. Ahora puede ejecutar un ejemplo muy específico, saber qué valor espera (y no darlo hoy para el valor de la prueba, porque hoy cambia con el tiempo). Si ingresa los valores que usó en el programa independiente, sus exámenes probablemente pasarán. Eso es genial, quieres que esos casos sigan funcionando. Ahora, agregue un valor de su informe, uno que no funciona bien. Tu nueva prueba probablemente falle. Averigua por qué está fallando, arréglalo y ponte verde (todas las pruebas pasan). Ejecute su informe. Vea lo que todavía está roto; escribe una prueba; hazlo pasar Muy pronto descubrirá que su informe está funcionando.


Ya he escrito sobre eso. Este es un reenvío de Cálculo de la diferencia entre dos instancias de fecha de Java .

public int getDiffernceInDays(long timeAfter, long timeBefore) { Calendar calendarAfter = Calendar.getInstance(); calendarAfter.setTime(new Date(timeAfter)); Calendar calendarNewAfter = Calendar.getInstance(); calendarNewAfter.set(calendarAfter.get(Calendar.YEAR), calendarAfter.get(Calendar.MONTH), calendarAfter.get(Calendar.DAY_OF_MONTH)); Calendar calendarBefore = Calendar.getInstance(); calendarBefore.setTime(new Date(timeBefore)); Calendar calendarNewBefore = Calendar.getInstance(); calendarNewBefore.set(calendarBefore.get(Calendar.YEAR), calendarBefore.get(Calendar.MONTH), calendarBefore.get(Calendar.DAY_OF_MONTH)); return (int) ((calendarNewAfter.getTime().getTime() - calendarNewBefore.getTime().getTime()) / (24 * 60 * 60 * 1000)); }


Yo uso esta función:

DATEDIFF("31/01/2016", "01/03/2016") // me return 30 days

mi función:

import java.util.Date; public long DATEDIFF(String date1, String date2) { long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000; long days = 0l; SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); // "dd/MM/yyyy HH:mm:ss"); Date dateIni = null; Date dateFin = null; try { dateIni = (Date) format.parse(date1); dateFin = (Date) format.parse(date2); days = (dateFin.getTime() - dateIni.getTime())/MILLISECS_PER_DAY; } catch (Exception e) { e.printStackTrace(); } return days; }


import java.util.Calendar; import java.util.Date; public class Main { public static long calculateDays(String startDate, String endDate) { Date sDate = new Date(startDate); Date eDate = new Date(endDate); Calendar cal3 = Calendar.getInstance(); cal3.setTime(sDate); Calendar cal4 = Calendar.getInstance(); cal4.setTime(eDate); return daysBetween(cal3, cal4); } public static void main(String[] args) { System.out.println(calculateDays("2012/03/31", "2012/06/17")); } /** Using Calendar - THE CORRECT WAY**/ public static long daysBetween(Calendar startDate, Calendar endDate) { Calendar date = (Calendar) startDate.clone(); long daysBetween = 0; while (date.before(endDate)) { date.add(Calendar.DAY_OF_MONTH, 1); daysBetween++; } return daysBetween; } }


public static int getDifferenceIndays(long timestamp1, long timestamp2) { final int SECONDS = 60; final int MINUTES = 60; final int HOURS = 24; final int MILLIES = 1000; long temp; if (timestamp1 < timestamp2) { temp = timestamp1; timestamp1 = timestamp2; timestamp2 = temp; } Calendar startDate = Calendar.getInstance(TimeZone.getDefault()); Calendar endDate = Calendar.getInstance(TimeZone.getDefault()); endDate.setTimeInMillis(timestamp1); startDate.setTimeInMillis(timestamp2); if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) { int day1 = endDate.get(Calendar.DAY_OF_MONTH); int day2 = startDate.get(Calendar.DAY_OF_MONTH); if (day1 == day2) { return 0; } else { return 1; } } int diffDays = 0; startDate.add(Calendar.DAY_OF_MONTH, diffDays); while (startDate.before(endDate)) { startDate.add(Calendar.DAY_OF_MONTH, 1); diffDays++; } return diffDays; }