1

Helo, I have a problem with the subtraction of two dates because the result is not correct:

  public static void main(String[] args) throws ParseException, InterruptedException{

  DateFormat format = new SimpleDateFormat("HH:mm:ss"); 
  long start = System.currentTimeMillis();
  Thread.sleep(3000);
  long goal = System.currentTimeMillis();

  long wyn = goal - start;
  Date result = new Date(wyn);
  System.out.println("Test1: " + format.format(result));
}

RESULT: Test1: 01:00:03

There should be only three seconds between start and stop - why is there one hour? (depend on summer/winter time?) I need count time between start and end my program and I just want to get hours, minutes and seconds. Can anyone help?

Connor Pearson
  • 63,902
  • 28
  • 145
  • 142
hetmanJIIIS
  • 106
  • 1
  • 11

4 Answers4

4

The Date class is not meant for intervals. It is meant for specific moment in time. The following

long wyn = goal - start;

will be equal to around 3000. That's 3000 milliseconds after Unix Epoch when used as an argument for the Date constructor. Depending on your timezone, that will be some number of hours + 3 seconds.


Consider using the Joda Time API which has an Interval interface you can use for calculating intervals.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • 1
    One note for the sake of correctness: it's [**Unix epoch**](http://en.wikipedia.org/wiki/Unix_time#History), not Linux epoch. – informatik01 Jan 04 '14 at 17:36
3

You are converting the interval into a Date object. This is wrong.

The Date object is used to represent a point in time, not an interval of time.

What you should do is the following:

long wyn = goal - start;
System.out.println("Test1: " + wyn); //prints the interval in milliseconds

Result:

Test1: 3000

If you construct a Date object using wyn, you're creating a Date object that represents the point in time 3 seconds after "the epoch" (January 1, 1970, 00:00:00 GMT).

The reason you see the hour is because time zones used in the year 1970 are different from those used now. For the same reason, I get Test1: 07:30:03.

ADTC
  • 8,999
  • 5
  • 68
  • 93
0

To get the format you want, without misusing the Date class:

  public static String toHMS(int milliseconds){
    DecimalFormat twoDigit = new DecimalFormat("00");
    int secs = milliseconds/1000;
    String secsString = twoDigit.format(secs%60);
    int minutes = secs/60;
    String minsString = twoDigit.format(minutes%60);
    int hours = minutes/60;
    String hoursString = twoDigit.format(hours);
    return hoursString + ":" + minsString + ":" + secsString;
  }
Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
0

The answer by ADTC is correct.

Rolling your own date-time calculations is risky business. Time zones, Daylight Savings Time (DST), and other anomalies make such attempts failure-prone.

And rolling your own is silly since we have well-written and debugged code at our disposal. Currently we have the Joda-Time library, and with Java 8 we'll have the new java.time.* classes (inspired by Joda-Time). Joda-Time has classes built just for the purpose you are trying to jerry-rig, handling a span of time.

The following is copied from an answer I posted recently to a similar question, showing how to properly define a span of time and render a string describing that span.


The Joda-Time 2.3 library makes this kind of work easier. Look at the Period, Duration, and Interval classes.

In contrast to a java.util.Date, in Joda-Time a DateTime instance does indeed know its assigned time zone.

The ISO 8601 standard defines a way to describe durations as hours, minutes, and such in a PnYnMnDTnHnMnS format. I use that in my example code below. Joda-Time offers other ways as well.

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;

DateTimeZone timeZone = DateTimeZone.forID( "Europe/London" );
DateTime dateTimeNew = new DateTime( timeZone );
DateTime dateTimeOld = dateTimeNew.minusHours( 2 );

Period period = new Period( dateTimeOld, dateTimeNew );

Dump to console…

System.out.println( "dateTimeNew: " + dateTimeNew );
System.out.println( "dateTimeOld: " + dateTimeOld );
System.out.println( "period: " + period );

When run…

dateTimeNew: 2014-01-02T23:19:45.021Z
dateTimeOld: 2014-01-02T21:19:45.021Z
period: PT2H
Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154