1

I have written a small program that shall print the difference between two Date objects:

public static void main(final String[] args) throws Exception {
    final DateFormat df = new SimpleDateFormat("HH:mm:ss.SSSSSS");
    final Date start = Calendar.getInstance().getTime();

    Thread.sleep(1000);

    final Date end = Calendar.getInstance().getTime();
    final long startMilliseconds = start.getTime();
    final long endMilliseconds = end.getTime();
    final long runtimeMilliseconds = endMilliseconds - startMilliseconds;
    final Date runtime = new Date(runtimeMilliseconds);

    System.out.print("Start  : " + df.format(start));
    System.out.println("\t Milliseconds: " + startMilliseconds);
    System.out.print("End    : " + df.format(end));
    System.out.println("\t Milliseconds: " + endMilliseconds);
    System.out.print("Runtime: " + df.format(runtime));
    System.out.println("\t Milliseconds: " + runtimeMilliseconds);
    System.out.println();
    System.out.println("Milliseconds from new Date object: " + runtime.getTime());
}

It gives the following output:

Start  : 13:24:54.000871     Milliseconds: 1408015494871
End    : 13:24:55.000871     Milliseconds: 1408015495871
Runtime: 01:00:01.000000     Milliseconds: 1000

Milliseconds from new Date object: 1000

The difference between the milliseconds is correct, but the newly created Date object has an extra hour added. The expected output for the runtime object would be: 00:00:01.000000. I think this is because of my timezone (GMT+1). How can I compute the difference between two Date objects and get a new Date object, that does not include the extra hour, back? I do not want to use Joda-Time or another library.

stevecross
  • 5,588
  • 7
  • 47
  • 85
  • Why `Calendar.getInstance().getTime()` but not just `System.currentTimeMillis()`? – Andremoniy Aug 14 '14 at 11:34
  • And actually it is unclear what you are asking: you have already wrote the code which do what you desire. – Andremoniy Aug 14 '14 at 11:35
  • It is just a test program. In my real program I need the Date objects, too. Expected output is `00:00:01.000000`, but actual output is `01:00:01.000000`. – stevecross Aug 14 '14 at 11:36
  • http://stackoverflow.com/questions/230126/how-to-handle-calendar-timezones-using-java – Stefan Aug 14 '14 at 11:40
  • 1
    You are trying to store an amount of time (for example, 1000 milliseconds) in a `Date` object. But a `Date` object is unsuitable for storing *amounts* of time. A `Date` object is a timestamp, which always has a date and time. If you store "1000" in a `Date` object, then what you get is a timestamp set to 01-01-1970 00:00:01 GMT. – Jesper Aug 14 '14 at 11:44
  • Okay, but for me the timestamp is set to `01-01-1970 01:00:01 GMT`. – stevecross Aug 14 '14 at 11:48
  • For all you timezone sayers, what is the time delta is more than 24 hours? Then this solution would produce a completely wrong result. Time Zone is not the answer here. Date is not being used correctly. – John B Aug 14 '14 at 12:01

4 Answers4

3

To reach your desired behavior you need to set the right time zone, i.e. GMT-00, because a Date object created with the constructor you use, will be the milliseconds since January 1, 1970, 00:00:00 GMT.

To do that simply set the DateFormat df:

df.setTimeZone(TimeZone.getTimeZone("GMT-00"));

immediately after its instantiation (then also Start and End dates will be displayed with the new time zone) or before the printing of the new Date runtime (then Start and End dates will be displayed in your local time zone); after that you can reset your original local timezone, if you want to keep it for future use.

The output will be of this kind as you desire:

Start  : 11:51:37.000287     Milliseconds: 1408017097287
End    : 11:51:38.000287     Milliseconds: 1408017098287
Runtime: 00:00:01.000000     Milliseconds: 1000

Milliseconds from new Date object: 1000
WoDoSc
  • 2,598
  • 1
  • 13
  • 26
  • This ignores the underlying issue, why store a time delta in a `Date` object? – John B Aug 14 '14 at 11:47
  • you're right, but I followed what he described as desired behavior of his code. – WoDoSc Aug 14 '14 at 11:51
  • Although it gives the correct output, if a peer or instructor were to review the code they might have to wonder, "is this really a Date?". – John B Aug 14 '14 at 11:57
  • The other point is, what if the time delta is more than 24 hours? This would then be completely wrong. – John B Aug 14 '14 at 11:59
  • I'm not an instructor nor a reviewer ;) And I don't think his code is for school-assignment nor a large business project, since he said that is just a test program :) But anyway, for sure from a theoretic point of view, you're right. – WoDoSc Aug 14 '14 at 12:01
2

You issue is that you are treating a time duration as a Date. 1000 ms does not make any sense as a Date since Date is MS since the epoch. Don't try to convert it to a Date, just use it as a long.

If you are using Java 8, consider Duration. Or you could use JodaTime. Seems like these might be overkill if you just need the long.

Per your question, to format it, it depends on if you are using Java 8. If so, use its Duration. Otherwise, use JodaTime & Duration, Period and PeriodFormatter. This is described in the post:

joda-time-period-to-string

I will admit this is a more complicated solution than setting the time-zone as others have suggested. However, I suggest it is a more correct solution. This is especially true if the time delta exceeds a day. In that case this solution would be completely wrong.

If the time delta is 24h 1sec, your format of HH:mm:ss.SSSSS would show 00:00:01.00000 instead of '24:00:01.0000`

Community
  • 1
  • 1
John B
  • 32,493
  • 6
  • 77
  • 98
  • How can I print the time delta in the format `HH:mm:ss.SSSSSS`? – stevecross Aug 14 '14 at 11:46
  • I understand what you are saying. Thanks for clarification. For now I will stick with the timezone solution since the differences wont exceed more than some minutes. But I will definitively take a look at Joda-Time, because I am still on java 7. – stevecross Aug 14 '14 at 12:06
  • Definitely check it out. It is a much better Date library than the built-in one for Java. That is why they added the update in Java 8. Since you know you are less than 24h you should be good. Cheers. – John B Aug 14 '14 at 12:09
0

Actually you are using Date class, and more specifically, SimpleDateFormat class in wrong way.

You wrote in your question everything right: additional hour in runtime object is due to your time zone (GMT+1).

The internal representation of your runtime object is time = 1000, i.e. it is 00:00:01 of January 1, 1970 GMT.

If you want to see exactly this date, you should modify your formatter in proper way:

    final DateFormat dfGmt0 = new SimpleDateFormat("HH:mm:ss.SSSSSS");
    dfGmt0.setTimeZone(TimeZone.getTimeZone("GMT+0"));
Andremoniy
  • 34,031
  • 20
  • 135
  • 241
0

You are getting this Runtime: 01:00:01.000000 Milliseconds: 1000 beacuse your current time zone is UTC+01:00 . set time zone GMT-00 for the Dateformatter .

Krishna Kant
  • 105
  • 9