0

I am trying to save the difference between two LocalDateTimes. So actually, I am looking for a class like Period which allows me to save date aswel as time (Since Period only allows me to save the date).

What class would let me do so?

assylias
  • 321,522
  • 82
  • 660
  • 783
logos
  • 61
  • 1
  • 8
  • 1
    How about Duration ? See: https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#between-java.time.temporal.Temporal-java.time.temporal.Temporal- – rgrebski Jun 13 '15 at 13:35
  • If i'm correct, duration does not also store dates in the form of years months and days but converts it to hours minutes and seconds – logos Jun 13 '15 at 13:47
  • Please describe more precisely your question, because now Im confused. Sample code would also be helpful – rgrebski Jun 13 '15 at 13:50
  • Why not store as long or int (milliseconds or seconds, whichever is more useful for your use case)? – Risadinha Jun 13 '15 at 14:49
  • I think this is a duplicate - see other post which contains much better answers (also [one related to Java-8 only](http://stackoverflow.com/a/25760725/2491410)). Anyway what is your final intention regarding the difference between two `LocalDateTime`-values? Okay, you want to store it, but then what follows? Do you want to print it later? If yes how? Any other use-cases? – Meno Hochschild Jun 15 '15 at 10:42

3 Answers3

2

The correct way is to decompose the difference by time unit such as in this answer.


Another option would be to save the date difference in a period and the time difference in a duration but this may lead to negative units in some cases:

LocalDateTime now = LocalDateTime.now();
LocalDateTime before = now.minusMonths(1).minusDays(5).minusHours(2).minusMinutes(30);
Period p = Period.between(before.toLocalDate(), now.toLocalDate());
Duration d = Duration.between(before.toLocalTime(), now.toLocalTime());

System.out.println(p + " + " + d);

which outputs: P1M5D + PT2H30M

Corner cases: if before = now.minusMonths(1).plusDays(1).plusMinutes(30);, the duration is minus 30 minutes. This can't easily be fixed because doing an intuitive:

if (d.isNegative()) {
  p = p.minusDays(1);
  d = d.plusDays(1);
}

Can return negative days in other cases.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
  • This is the implementation I have chosen – logos Jun 13 '15 at 18:49
  • There is one big problem with this code. In some cases users can get expressions with mixed signs, for example plus one month minus 1 hour. – Meno Hochschild Jun 15 '15 at 10:46
  • @MenoHochschild You are right - thanks. I have edited accordingly (although I'm not 100% sure it handles DST properly - it probably would). – assylias Jun 15 '15 at 11:46
  • Sorry for again annoying but what will you do for this input: before=[2015-05-15T23:00], now=[2015-06-15T00:00] I get with your new code: (plus one month minus one day) and a `Duration` of plus one hour. Well, one month is always bigger than one day, but I would not dare to present such a "duration/period" to the end user. The accepted answer in the duplicate link handles this month/day-boundary case however. – Meno Hochschild Jun 15 '15 at 12:07
  • @MenoHochschild Thanks for your input - you are right there too. I agree with your point that this is not the right approach and have amended accordingly. – assylias Jun 15 '15 at 12:19
1

I think you should convert both of them in millis then make a subtraction.

LocalDateTime a, b;
long timeInMillis = Math.abs(a.toDateTime().getMillis() - b.toDateTime().getMillis());

You will then get the period in milliseconds.

Pâris Douady
  • 833
  • 8
  • 18
  • Thank you, but the calculation is not the issue. It's the storing in the form of year/month/day/hour/minute/second which is the problem. – logos Jun 13 '15 at 13:48
  • @logos You probably wouldn't want to store it as y/m/d/h/m/s, since year and month can change length depending on when the period would take place. Storing the raw milliseconds and doing the conversion when you need to use it would be more robust. – Kiskae Jun 13 '15 at 14:00
1
 @Test
    public void durationTest(){
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime nowMinus5s = now.minusSeconds(5);

        assertThat(Duration.between(now, nowMinus5s).getSeconds()).isEqualTo(-5);
    }
rgrebski
  • 2,354
  • 20
  • 29