views:

2560

answers:

3

I created the following code to calculate the duration between two timestamps which can come in two different formats:

public class dummyTime {
public static void main(String[] args) {
 try {
  convertDuration("2008-01-01 01:00 pm - 01:56 pm");
  convertDuration("2008-01-01 8:30 pm - 2008-01-02 09:30 am");
 } catch (Exception e) {
  e.printStackTrace();
 }
}

private static String convertDuration(String time) throws Exception {
 String ts[] = time.split(" - ");
 SimpleDateFormat formatNew = new SimpleDateFormat("HH:mm");
 Date beg, end;
 String duration = null;

 beg = getDateTime(ts[0]);
 end = getDateTime(ts[1], beg);

 duration = formatNew.format(end.getTime() - beg.getTime());
 System.out.println(duration + " /// " + time + " /// " + beg + " /// "
   + end);

 return duration;
}

private static Date getDateTime(String dateTime) throws ParseException {
 DateFormat formatOldDateTime = new SimpleDateFormat(
   "yyyy-MM-dd hh:mm aa");
 DateFormat formatOldTimeOnly = new SimpleDateFormat("hh:mm aa");
 Date date = null;

 try {
  date = formatOldDateTime.parse(dateTime);
 } catch (ParseException e) {
  date = formatOldTimeOnly.parse(dateTime);
 }

 return date;
}

private static Date getDateTime(String dateTime, Date orig)
  throws ParseException {
 Date end = getDateTime(dateTime);

 if (end.getYear() == 70) {
  end.setYear(orig.getYear());
  end.setMonth(orig.getMonth());
  end.setDate(orig.getDate());
 }

 return end;
}
}

The output it generates is:

01:56 /// 2008-01-01 01:00 pm - 01:56 pm /// Tue Jan 01 13:00:00 CET 2008 /// Tue Jan 01 13:56:00 CET 2008
14:00 /// 2008-01-01 8:30 pm - 2008-01-02 09:30 am /// Tue Jan 01 20:30:00 CET 2008 /// Wed Jan 02 09:30:00 CET 2008

My questions are:

  1. Why are the results always wrong (always +1h)?
  2. What is a better way to identify timestamps without day? == 70 doesn't look good and the getDay & setDay functions are deprecated too.

Many many thanks, this issue has been driving me crazy for several hours.

+4  A: 

You are formatting time of day, not number of hours and minutes. As you are in the CET timezone [Central European Time] in winter, that is one hour different from UTC ("GMT").

You probably want to be using Calendar instead of Date. Or Joda-Time.

Tom Hawtin - tackline
I thought that might be popular.
Tom Hawtin - tackline
+1  A: 
  1. At my computer this is off by 2 hours, because I'm at GMT+2, and you're probably at GMT+1. Note that formatNew.format(end.getTime() - beg.getTime()); receives date, i.e. treats your 56 minutes as 1970-01-01-00:56:00 GMT+1. To fix this quickly, call formatNew.setTimeZone( TimeZone.getTimeZone( "GMT" ) );

  2. For the 2nd item, you can check if format-yyyy-MM-dd failed (you catch a parse error), and this is how you know that there's no year.

Yoni Roit
JODA Time http://joda-time.sourceforge.net/
basszero
A: 

Simple answer: it's inappropriate to use SimpleDateFormat to format values that represent time of day without date.

Longer answer: Java time values are a count of milliseconds since the "epoch": midnight, January 1 1970, UTC.

SimpleDateFormat assumes that you're giving it a valid timestamp, and applies a localized conversion to a date and time. I suspect that your locale is one hour off GMT (continental Europe), so that's why you're seeing results that are one hour off.

While you could fool SimpleDateFormat by setting the timezone GMT, you're probably better off displaying durations using explicit math:

int duration = 90;
System.out.printf("%02d:%02d", duration / 60, duration % 60);
kdgregory