简体   繁体   中英

How to get number of months, weeks, days and hours from now to a future time?

I need to find out the number of months, weeks, days and hours left from now to a future time using Java. I can not use any third party library like Joda. How can I do that using just JDK classes?

So far, this is what I have come up with. It sort of works, except for some situations:

public class DateUtil {

public static Integer[] components(Date from, Date to) {
    Integer[] result = new Integer[4];
    //SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    //df.setTimeZone(TimeZone.getTimeZone("EST"));

    Calendar fromCal = new GregorianCalendar();
    Calendar toCal = new GregorianCalendar();

    fromCal.setTime(from);
    toCal.setTime(to);

    int months = 0;
    do {
        fromCal.add(Calendar.MONTH, 1);
        ++months;
        //System.out.println(df.format(fromCal.getTime()));
    } while (fromCal.before(toCal));

    fromCal.add(Calendar.MONTH, -1);
    --months;

    int days = 0;
    do {
        fromCal.add(Calendar.DAY_OF_YEAR, 1);
        ++days;
    } while (fromCal.before(toCal));

    fromCal.add(Calendar.DAY_OF_YEAR, -1);
    --days;

    int hours = 0;
    do {
        fromCal.add(Calendar.HOUR_OF_DAY, 1);
        ++hours;
    } while (fromCal.before(toCal));

    fromCal.add(Calendar.HOUR_OF_DAY, -1);
    --hours;

    int minutes = 0;
    do {
        fromCal.add(Calendar.MINUTE, 1);
        ++minutes;
    } while (fromCal.before(toCal));

    result[0] = months;
    result[1] = days;
    result[2] = hours;
    result[3] = minutes;

    return result;
}

public static void main(String[] args) {
    try {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        df.setTimeZone(TimeZone.getTimeZone("EST"));

        Date from = df.parse("2014-03-29 00:00");
        Date to = df.parse("2014-05-29 00:00");
        Integer result[] = components(from, to);

        System.out.printf("Months:%02d Days:%02d Hrs:%02d Mins:%02d\n", 
                result[0], result[1], result[2], result[3]);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

It produces unacceptable results when you have February in the middle and start date is end of the month. For example:

From: Dec 31, 2013 To: Dec 31, 2014

The difference will produce: 12 months, 3 days.

Why not use the Java classes Date and Calendar

These classes already have built in functionality to help you calculate difference between two Dates. Most of the Date methods seem to be deprecated so instead I would recommend Calendar. Good luck!

One of my colleagues eventually came up with the right answer. The problem with incrementally adding a month to a Calendar is that you go from Jan 31 to Feb 28 to Mar 28, instead of Mar 31. This adds inaccuracy. The solution is to add 1 month, 2 months, 3 months and so on to the original start date. Then you go from Jan 31 to feb 28 to Mar 31. Anyway, here is his solution, slightly altered by me.

public class TimeSpan {
    public int months;
    public int days;
    public int hours;
    public int minutes;
}

class DateCalculator {
    public static TimeSpan difference(Date later, Date earlier) {
        TimeSpan v = new TimeSpan();

        /* Add months until we go past the target, then go back one. */
        while (calculateOffset(earlier, v).compareTo(later) <= 0) {
            v.months++;
        }
        v.months--;

        /* Add days until we go past the target, then go back one. */
        while (calculateOffset(earlier, v).compareTo(later) <= 0) {
            v.days++;
        }
        v.days--;

        /* Add hours until we go past the target, then go back one. */
        while (calculateOffset(earlier, v).compareTo(later) <= 0) {
            v.hours++;
        }
        v.hours--;
        while (calculateOffset(earlier, v).compareTo(later) <= 0) {
            v.minutes++;
        }
        v.minutes--;

        return v;
    }

    private static Date calculateOffset(Date start, TimeSpan offset) {
        Calendar c = new GregorianCalendar();

        c.setTime(start);

        c.add(Calendar.MONTH, offset.months);
        c.add(Calendar.DAY_OF_YEAR, offset.days);
        c.add(Calendar.HOUR, offset.hours);
        c.add(Calendar.MINUTE, offset.minutes);

        return c.getTime();
    }
     public static void main(String[] args) {
            try {
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    df.setTimeZone(TimeZone.getTimeZone("EST"));

                    Date from = df.parse("2013-01-31 00:00");
                    Date to = df.parse("2014-01-31 10:20");
                    TimeSpan ts = difference(to, from);

                    System.out.printf("Months:%02d Days:%02d Hrs:%02d Mins:%02d\n",
                                    ts.months, ts.days, ts.hours, ts.minutes);
            } catch (Exception e) {
                    e.printStackTrace();
            }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM