two hours dates java date datetime java-8 difference

hours - Java 8: Calcular la diferencia entre dos LocalDateTime



java difference between dates in days (8)

Estoy tratando de calcular la diferencia entre dos LocalDateTime .

La salida debe tener el formato y years m months d days h hours m minutes s seconds . Aquí está lo que he escrito:

import java.time.Duration; import java.time.Instant; import java.time.LocalDateTime; import java.time.Period; import java.time.ZoneId; public class Main { static final int MINUTES_PER_HOUR = 60; static final int SECONDS_PER_MINUTE = 60; static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR; public static void main(String[] args) { LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 9, 19, 46, 45); LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55); Period period = getPeriod(fromDateTime, toDateTime); long time[] = getTime(fromDateTime, toDateTime); System.out.println(period.getYears() + " years " + period.getMonths() + " months " + period.getDays() + " days " + time[0] + " hours " + time[1] + " minutes " + time[2] + " seconds."); } private static Period getPeriod(LocalDateTime dob, LocalDateTime now) { return Period.between(dob.toLocalDate(), now.toLocalDate()); } private static long[] getTime(LocalDateTime dob, LocalDateTime now) { LocalDateTime today = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), dob.getHour(), dob.getMinute(), dob.getSecond()); Duration duration = Duration.between(today, now); long seconds = duration.getSeconds(); long hours = seconds / SECONDS_PER_HOUR; long minutes = ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE); long secs = (seconds % SECONDS_PER_MINUTE); return new long[]{hours, minutes, secs}; } }

El resultado que obtengo es 29 years 8 months 24 days 12 hours 0 minutes 50 seconds . Verifiqué mi resultado desde este website (con valores 12/16/1984 07:45:55 y 09/09/2014 19:46:45 ). La siguiente captura de pantalla muestra el resultado:

Estoy bastante seguro de que los campos después del valor del mes salen mal de mi código. Cualquier sugerencia sería de gran ayuda.

Actualizar

He probado mi resultado de otro sitio web y el resultado que obtuve es diferente. Aquí está: Calcule la duración entre dos fechas (resultado: 29 años, 8 meses, 24 días, 12 horas, 0 minutos y 50 segundos).

Actualizar

Como obtuve dos resultados diferentes de dos sitios diferentes, me pregunto si el algoritmo de mi cálculo es legítimo o no. Si uso los siguientes dos objetos LocalDateTime :

LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45); LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);

Entonces la salida se acerca: 29 years 8 months 25 days -1 hours -5 minutes -10 seconds.

Desde este link debe ser 29 years 8 months 24 days 22 hours, 54 minutes and 50 seconds . Entonces el algoritmo también necesita manejar los números negativos.

Tenga en cuenta que la pregunta no es sobre qué sitio me dio qué resultado, necesito saber el algoritmo correcto y tener los resultados correctos.


¡Debería ser más simple!

Duration.between(startLocalDateTime, endLocalDateTime).toMillis();


Aquí hay una respuesta muy simple a su pregunta. Funciona.

import java.time.*; import java.util.*; import java.time.format.DateTimeFormatter; public class MyClass { public static void main(String args[]) { DateTimeFormatter T = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"); Scanner h = new Scanner(System.in); System.out.print("Enter date of birth[dd/mm/yyyy hh:mm]: "); String b = h.nextLine(); LocalDateTime bd = LocalDateTime.parse(b,T); LocalDateTime cd = LocalDateTime.now(); int hr = cd.getHour() - bd.getHour(); int mn = cd.getMinute() - bd.getMinute(); Period time = Period.between(bd.toLocalDate(),cd.toLocalDate()); System.out.print("Age is: "+time.getYears()+ " years,"+time.getMonths()+ " months, " +time.getDays()+ " days, "+hr+ " hours, " +mn+ " minutes old"); } }


Aquí un solo ejemplo usando Duration y TimeUnit para obtener el formato ''hh: mm: ss''.

Duration dur = Duration.between(localDateTimeIni, localDateTimeEnd); long millis = dur.toMillis(); String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis), TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));


Como muchas de las respuestas requerían compatibilidad con API 26 y mi API mínima era 23, lo resolví con el siguiente código:

import org.joda.time.Days LocalDate startDate = Something LocalDate endDate = Something // The difference would be exclusive of both dates, // so in most of use cases we may need to increment it by 1 Days.daysBetween(startDate, endDate).days


Desafortunadamente, no parece haber una clase de período que abarque también el tiempo, por lo que es posible que tenga que hacer los cálculos por su cuenta.

Afortunadamente, las clases de fecha y hora tienen muchos métodos de utilidad que simplifican eso hasta cierto punto. Aquí hay una manera de calcular la diferencia, aunque no necesariamente la más rápida:

LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55); LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45); LocalDateTime tempDateTime = LocalDateTime.from( fromDateTime ); long years = tempDateTime.until( toDateTime, ChronoUnit.YEARS); tempDateTime = tempDateTime.plusYears( years ); long months = tempDateTime.until( toDateTime, ChronoUnit.MONTHS); tempDateTime = tempDateTime.plusMonths( months ); long days = tempDateTime.until( toDateTime, ChronoUnit.DAYS); tempDateTime = tempDateTime.plusDays( days ); long hours = tempDateTime.until( toDateTime, ChronoUnit.HOURS); tempDateTime = tempDateTime.plusHours( hours ); long minutes = tempDateTime.until( toDateTime, ChronoUnit.MINUTES); tempDateTime = tempDateTime.plusMinutes( minutes ); long seconds = tempDateTime.until( toDateTime, ChronoUnit.SECONDS); System.out.println( years + " years " + months + " months " + days + " days " + hours + " hours " + minutes + " minutes " + seconds + " seconds."); //prints: 29 years 8 months 24 days 22 hours 54 minutes 50 seconds.

La idea básica es esta: cree una fecha de inicio temporal y obtenga los años completos hasta el final. Luego ajuste esa fecha por la cantidad de años para que la fecha de inicio sea inferior a un año desde el final. Repita eso para cada unidad de tiempo en orden descendente.

Finalmente, un descargo de responsabilidad: no tomé en cuenta diferentes zonas horarias (ambas fechas deberían estar en la misma zona horaria) y tampoco probé / verifiqué cómo el horario de verano u otros cambios en un calendario (como la zona horaria cambia en Samoa) afectar este cálculo Así que úsalo con cuidado.



Hay algún problema para el código Tapas Bose y el código Thomas. Si la diferencia de tiempo es negativa, la matriz obtiene los valores negativos. Por ejemplo si

LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45); LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);

devuelve 0 años 0 meses 1 días -1 horas 0 minutos 0 segundos.

Creo que la salida correcta es: 0 años 0 meses 0 días 23 horas 0 minutos 0 segundos.

Propongo separar las instancias LocalDateTime en las instancias LocalDate y LocalTime. Después de eso, podemos obtener las instancias de período y duración de Java 8. La instancia de Duración se separa en el número de días y el valor de tiempo a lo largo del día (<24 h) con la corrección posterior del valor del período. Cuando el segundo valor de LocalTime es anterior al primer valor de LocalTime, es necesario reducir el período de un día.

Aquí está mi manera de calcular la diferencia LocalDateTime:

private void getChronoUnitForSecondAfterFirst(LocalDateTime firstLocalDateTime, LocalDateTime secondLocalDateTime, long[] chronoUnits) { /*Separate LocaldateTime on LocalDate and LocalTime*/ LocalDate firstLocalDate = firstLocalDateTime.toLocalDate(); LocalTime firstLocalTime = firstLocalDateTime.toLocalTime(); LocalDate secondLocalDate = secondLocalDateTime.toLocalDate(); LocalTime secondLocalTime = secondLocalDateTime.toLocalTime(); /*Calculate the time difference*/ Duration duration = Duration.between(firstLocalDateTime, secondLocalDateTime); long durationDays = duration.toDays(); Duration throughoutTheDayDuration = duration.minusDays(durationDays); Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO, "Duration is: " + duration + " this is " + durationDays + " days and " + throughoutTheDayDuration + " time."); Period period = Period.between(firstLocalDate, secondLocalDate); /*Correct the date difference*/ if (secondLocalTime.isBefore(firstLocalTime)) { period = period.minusDays(1); Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO, "minus 1 day"); } Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO, "Period between " + firstLocalDateTime + " and " + secondLocalDateTime + " is: " + period + " and duration is: " + throughoutTheDayDuration + "/n-----------------------------------------------------------------"); /*Calculate chrono unit values and write it in array*/ chronoUnits[0] = period.getYears(); chronoUnits[1] = period.getMonths(); chronoUnits[2] = period.getDays(); chronoUnits[3] = throughoutTheDayDuration.toHours(); chronoUnits[4] = throughoutTheDayDuration.toMinutes() % 60; chronoUnits[5] = throughoutTheDayDuration.getSeconds() % 60; }

El método anterior se puede usar para calcular la diferencia de cualquier valor de fecha y hora local, por ejemplo:

public long[] getChronoUnits(String firstLocalDateTimeString, String secondLocalDateTimeString) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime firstLocalDateTime = LocalDateTime.parse(firstLocalDateTimeString, formatter); LocalDateTime secondLocalDateTime = LocalDateTime.parse(secondLocalDateTimeString, formatter); long[] chronoUnits = new long[6]; if (secondLocalDateTime.isAfter(firstLocalDateTime)) { getChronoUnitForSecondAfterFirst(firstLocalDateTime, secondLocalDateTime, chronoUnits); } else { getChronoUnitForSecondAfterFirst(secondLocalDateTime, firstLocalDateTime, chronoUnits); } return chronoUnits; }

Es conveniente escribir una prueba unitaria para el método anterior (ambos son miembros de la clase PeriodDuration). Aquí está el código:

@RunWith(Parameterized.class) public class PeriodDurationTest { private final String firstLocalDateTimeString; private final String secondLocalDateTimeString; private final long[] chronoUnits; public PeriodDurationTest(String firstLocalDateTimeString, String secondLocalDateTimeString, long[] chronoUnits) { this.firstLocalDateTimeString = firstLocalDateTimeString; this.secondLocalDateTimeString = secondLocalDateTimeString; this.chronoUnits = chronoUnits; } @Parameters public static Collection<Object[]> periodValues() { long[] chronoUnits0 = {0, 0, 0, 0, 0, 0}; long[] chronoUnits1 = {0, 0, 0, 1, 0, 0}; long[] chronoUnits2 = {0, 0, 0, 23, 0, 0}; long[] chronoUnits3 = {0, 0, 0, 1, 0, 0}; long[] chronoUnits4 = {0, 0, 0, 23, 0, 0}; long[] chronoUnits5 = {0, 0, 1, 23, 0, 0}; long[] chronoUnits6 = {29, 8, 24, 12, 0, 50}; long[] chronoUnits7 = {29, 8, 24, 12, 0, 50}; return Arrays.asList(new Object[][]{ {"2015-09-09 21:46:44", "2015-09-09 21:46:44", chronoUnits0}, {"2015-09-09 21:46:44", "2015-09-09 22:46:44", chronoUnits1}, {"2015-09-09 21:46:44", "2015-09-10 20:46:44", chronoUnits2}, {"2015-09-09 21:46:44", "2015-09-09 20:46:44", chronoUnits3}, {"2015-09-10 20:46:44", "2015-09-09 21:46:44", chronoUnits4}, {"2015-09-11 20:46:44", "2015-09-09 21:46:44", chronoUnits5}, {"1984-12-16 07:45:55", "2014-09-09 19:46:45", chronoUnits6}, {"2014-09-09 19:46:45", "1984-12-16 07:45:55", chronoUnits6} }); } @Test public void testGetChronoUnits() { PeriodDuration instance = new PeriodDuration(); long[] expResult = this.chronoUnits; long[] result = instance.getChronoUnits(this.firstLocalDateTimeString, this.secondLocalDateTimeString); assertArrayEquals(expResult, result); }

}

Todas las pruebas tienen éxito independientemente de si el valor del primer LocalDateTime es anterior y para cualquier valor de LocalTime.


Y la versión de @Thomas en Groovy con toma las unidades deseadas en una lista en lugar de codificar los valores. Esta implementación (que puede portarse fácilmente a Java, hice explícita la declaración de la función) hace que Thomas enfoque sea más reutilizable.

def fromDateTime = LocalDateTime.of(1968, 6, 14, 0, 13, 0) def toDateTime = LocalDateTime.now() def listOfUnits = [ ChronoUnit.YEARS, ChronoUnit.MONTHS, ChronoUnit.DAYS, ChronoUnit.HOURS, ChronoUnit.MINUTES, ChronoUnit.SECONDS, ChronoUnit.MILLIS] println calcDurationInTextualForm(listOfUnits, fromDateTime, toDateTime) String calcDurationInTextualForm(List<ChronoUnit> listOfUnits, LocalDateTime ts, LocalDateTime to) { def result = [] listOfUnits.each { chronoUnit -> long amount = ts.until(to, chronoUnit) ts = ts.plus(amount, chronoUnit) if (amount) { result << "$amount ${chronoUnit.toString()}" } } result.join('', '') }

Al momento de escribir esto, el código anterior devuelve 47 Years, 8 Months, 9 Days, 22 Hours, 52 Minutes, 7 Seconds, 140 Millis . Y, para la entrada de @Gennady Kolomoets, el código devuelve 23 Hours .

Cuando proporciona una lista de unidades, debe ordenarse por tamaño de las unidades (la más grande primero):

def listOfUnits = [ChronoUnit.WEEKS, ChronoUnit.DAYS, ChronoUnit.HOURS] // returns 2495 Weeks, 3 Days, 8 Hours