3

Im trying to calculate the time difference between 2 Timestamps, this is the code:

        Calendar calendar = Calendar.getInstance();
        java.util.Date now = calendar.getTime();
        Timestamp currentTimestamp = new Timestamp(now.getTime());
        System.out.println("Current\n"+currentTimestamp);

        DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        Date date = dateFormat.parse("28/02/2015");
        Timestamp timestampBefore = new Timestamp(date.getTime());
        System.out.println("Before\n"+timestampBefore);

        Timestamp calculated = new Timestamp(currentTimestamp.getTime() - timestampBefore.getTime());
        System.out.println("Calculated\n"+calculated);

Output:

Current
2015-02-28 12:12:40.975
Before
2015-02-28 00:00:00.0
Calculated
1970-01-01 13:12:40.975
  1. I can understand why it returns 1970-01-01 but why does it return 13:12:40.975 ,1 hour more?

  2. How to calculate the difference between 2 dates so the output is like this (based on this example):
    Years:0, Months:0, Days:0, Hours:12, Minutes:12, Seconds:40 ?

Update: for java below 1.8 check out http://www.joda.org/joda-time/index.html
and for java 1.8 see answer.

Similar solution here: Java 8: Calculate difference between two LocalDateTime

Community
  • 1
  • 1
Alpha2k
  • 2,212
  • 7
  • 38
  • 65
  • 3
    The difference between two timestamps is not a timestamp, but a duration. It is useless to convert it to a date/time. – isnot2bad Feb 28 '15 at 11:24
  • I think it is a problem with the timezone. can you print calculated time with timezone? – Jens Feb 28 '15 at 11:24
  • @Jens the timezone shouldnt be a problem, its the exact hour (12:12:40.975) as my pc hour. – Alpha2k Feb 28 '15 at 11:26
  • 2
    Basically, the solution here is to use Joda Time or `java.time`. Do *not* treat a duration as a date/time. – Jon Skeet Feb 28 '15 at 11:30
  • @JonSkeet Damn, really appreciate a Google’s engineer spending time on such questions :) – Alpha2k Feb 28 '15 at 11:57
  • I disagree with your "Update" statement. Joda-Time works perfectly well in Java 8. While java.time was inspired by Joda-Time, it is re-architected. Both Joda-Time and java-time each have their strengths and weaknesses including features the other lacks. You can use both in a project as needed. – Basil Bourque Feb 28 '15 at 16:24

1 Answers1

5

(1) A timestamp is a point in time. If you calculate the difference between two timestamps, the result is not a timestamp (point in time), but a duration. So it is nonsense to convert the difference to a timestamp, hence it is useless to discuss the reason why the result is strange.

(2) You should probably use the new Java 8 time API (if you are able to use Java 8):

LocalTime now = LocalTime.now();
LocalTime previous = LocalTime.of(0, 0, 0, 0);
Duration duration = Duration.between(previous, now);

System.out.println(now);
System.out.println(previous);
System.out.println(duration);

Note that this just calculates the duration between two times of a day (hour-minute-second). If your want to include date information, use LocalDateTime instead:

LocalDateTime nextFirework = LocalDate.now()
                             .with(TemporalAdjusters.firstDayOfNextYear())
                             .atTime(LocalTime.MIDNIGHT);
LocalDateTime now = LocalDateTime.now();

// duration (in seconds and nanos)
Duration duration = Duration.between(now, nextFirework);
// duration in total hours
long hours = now.until(nextFirework, ChronoUnit.HOURS);
// equals to: duration.toHours();

If you want to have 'normalized' duration in years/months/days/hours/seconds, there is suprisingly no direct support. You could convert the duration to days, hours, minutes and seconds by yourself:

long d = duration.toDays();
long h = duration.toHours() - 24 * d;
long m = duration.toMinutes() - 60 * duration.toHours();
long s = duration.getSeconds() - 60 * duration.toMinutes();
System.out.println(d + "d " + h + "h " + m + "m " + s + "s ");

But note that you will have difficulties converting the days into months and years, as there is no unique number of days per month and a year can be a leap year with 366 days. For that, you can use Period, as in opposite to Duration, this class is associated with a timeline. Unfortunately, Period does only support dates, but no times:

// period in years/months/days (ignoring time information)
Period p = Period.between(now.toLocalDate(), nextFirework.toLocalDate());
System.out.println(p); // or use p.getYears(), p.getMonths(), p.getDays()

So probably you could combine both approaches - first, compute the Period from the dates and then the Duration using the times. Note that the duration can be negative, so you'll have to take care of that in case of:

Duration dur = Duration.between(start.toLocalTime(), end.toLocalTime());
LocalDate e = end.toLocalDate();
if (dur.isNegative()) {
    dur = dur.plusDays(1);
    e = e.minusDays(1);
}
Period per = Period.between(start.toLocalDate(), e);
System.out.println(per.toString() + ", " + dur.toString());
isnot2bad
  • 24,105
  • 2
  • 29
  • 50
  • how can i get ONLY hour of duration? Is there anything similar to duration.getHour()? – Alpha2k Feb 28 '15 at 12:06
  • That's ambiguous: Do you want to have the total duration in hours, or just the hour part of a normalized duration in the form years+months+days+hours+minutes+seconds? – isnot2bad Feb 28 '15 at 12:10
  • id like the output to be like this: Years:0, Months:0, Days:0, Hours:12, Minutes:12, Seconds:40 , everything "normalized". I tought of getting the duration and splitting it into small strings but i bet theres a better way of doing it. – Alpha2k Feb 28 '15 at 12:25
  • See my edit. It is not that trivial as months (28-31 days) and years (365-366 days) have no unique definition. And of course daylight saving adds more complexity... – isnot2bad Feb 28 '15 at 14:30
  • got it here: http://stackoverflow.com/questions/25747499/java-8-calculate-difference-between-two-localdatetime ,this is what i wanted, now im not sure if it manages to get the leaps correclty. – Alpha2k Feb 28 '15 at 14:45
  • Joda-Time does support defining a span of time as hours, days, and such. See the [`Period`](http://www.joda.org/joda-time/apidocs/org/joda/time/Period.html) class. By the way, [ISO 8601](http://en.m.wikipedia.org/wiki/ISO_8601) [defines](http://en.m.wikipedia.org/wiki/ISO_8601#Durations) a String format for hours days and such: `PnYnMnDTnHnMnS` where the `P` marks the beginning and the `T` separates date portion from time portion. So `P3DT2H` means "three days and two hours". Joda-Time generates and parses such strings by default. – Basil Bourque Feb 28 '15 at 16:20
  • @Alpha2k The SO answer you mention does not support the case where the time of the second date-time value is less than the time of the first date-time value; It will return a negative time in this case. (e.g. today at 3 pm until tomorrow 2 pm will return "1 day -1 hour" instead of "23 hours") – isnot2bad Feb 28 '15 at 22:35