Grains
Grains

Reputation: 950

Getting duration of 2 times

How can I get the duration of two Strings in the format YYYYMMDDTHHMMSS?

I´m trying with using the Calendar class and checking the getTimeInMillis(). Problem I am having with this is that it is not consistent. Any idea what I am doing wrong? Every time I run this program I get 40-70 lines of output to console when it should be none.

public class DurationTester {

    /**
     * Get the duration between two given times
     * @param time1 yyyymmddThhmmss
     * @param time2 yyyymmddThhmmss
     * @return minutes between time1 and time2
     */
    public static int getDuration(String time1, String time2){
        int yyyy1 = Integer.parseInt(time1.substring(0,4));
        int mm1 = Integer.parseInt(time1.substring(4,6));
        int dd1 = Integer.parseInt(time1.substring(6,8));
        int hh1 = Integer.parseInt(time1.substring(9,11));
        int min1 = Integer.parseInt(time1.substring(11,13));

        int yyyy2 = Integer.parseInt(time2.substring(0,4));
        int mm2 = Integer.parseInt(time2.substring(4,6));
        int dd2 = Integer.parseInt(time2.substring(6,8));
        int hh2 = Integer.parseInt(time2.substring(9,11));
        int min2 = Integer.parseInt(time2.substring(11,13));

        Calendar cal1 = Calendar.getInstance();
        cal1.set(yyyy1, mm1, dd1, hh1, min1, 0);
        Calendar cal2 = Calendar.getInstance();
        cal2.set(yyyy2, mm2, dd2, hh2, min2, 0);
        long milliSec = cal1.getTimeInMillis()-cal2.getTimeInMillis();
        long nonNegativeMS = Math.abs(milliSec);
        long seconds = nonNegativeMS / 1000;
        long minutes = seconds / 60;        
        return (int)minutes;
    }

    public static void main(String[] args){
        String t1 = "20130108T150000";
        String t2 = "20130108T131500";

        int errors = 0;
        for(int i=0; i<5000; i++){
            int duration = getDuration(t1,t2);
            if(duration == 104){
                System.out.println("ERROR: Should only be 105 ("+errors++ +")");
            }
        }
    }
}

Upvotes: 1

Views: 282

Answers (5)

MadProgrammer
MadProgrammer

Reputation: 347244

To start with, your date conversion is off Calendar months are zero indexed (that is Janurary is actually month 0), so instead of begin Tue Jan 08 15:00:00 EST 2013, you dates are actually being converted to Fri Feb 08 15:00:00 EST 2013, which, in of itself, is not the source of the problem, but is of concern.

Instead, you should be using ...

public static final SimpleDateFormat SDF = new SimpleDateFormat("yyyyMMdd'T'HHmmss");

public static int getDuration(String time1, String time2){
    Date date1 = SDF.parse(time1);
    Date date2 = SDF.parse(time2);

    Calendar cal1 = Calendar.getInstance();
    cal1.setTime(date1);
    Calendar cal2 = Calendar.getInstance();
    cal2.setTime(date2);

To convert the String values back to Date

Now, to the cause of your problem...

Because you are setting the Calendar values using the set(int year, int month, int date, int hourOfDay, int minute, int second), the calendar instance still contains the milliseconds it had when it was created (Calendar.getInstance() will return a Calendar set to the date/time it was created), but you are not zeroing out these values.

This leads to errors in your calculations

You shouldn't rely on Calendar or Date for calculating durations, they are unreliable over long periods, instead you should use JodaTime

DateTime dt1 = new DateTime(date1);
DateTime dt2 = new DateTime(date2);

Duration duration = new Duration(dt2, dt1);
System.out.println(duration.getStandardDays());
System.out.println(duration.getStandardHours());
System.out.println(duration.getStandardMinutes());

Upvotes: 1

Luis Sep
Luis Sep

Reputation: 2402

That's a documented bug.

Try clearing the calendar before set:

cal1.clear();
cal1.set(yyyy1, mm1, dd1, hh1, min1, 0);

cal2.clear();
cal2.set(yyyy2, mm2, dd2, hh2, min2, 0);

Upvotes: 2

user2663404
user2663404

Reputation: 21

You can use SimpleDateFormat API for parse your String :

public static void main(String[] args) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    try {
        Date date1 = sdf.parse("20130108T150000");
        Date date2 = sdf.parse("20130108T131500");
        System.out.println((date1.getTime() - date2.getTime())/1000/60);
    } catch (ParseException e) {
       e.printStackTrace();
    }
}

Upvotes: 2

Ruchira Gayan Ranaweera
Ruchira Gayan Ranaweera

Reputation: 35557

Try this

    String t1 = "20130108T150000";
    String t2 = "20130108T131500";
    DateFormat df=new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    Date date1=df.parse(t1);
    Date date2=df.parse(t2);

    System.out.println(date2.getTime()-date1.getTime());  // time difference in mil-seconds

Upvotes: 1

Ashish
Ashish

Reputation: 520

i would advice to use the SimpleDateFormat for parsing your String to date object

SimpleDateFormat date_format = new SimpleDateFormat("yyyyMMdd'T'HHmmSS");
Date dateParsed = date_format.parse(yourStringDate)

You can use the Date.getTime() function to obtain the date object equivalent in milisecond and perform the difference between two date object

Upvotes: 1

Related Questions