我需要找出使用Java从现在到未来时间的剩余月数,周数,天数和小时数。我不能使用像Joda这样的任何第三方库。我怎么能只使用JDK类呢?
到目前为止,这是我想出的。它除了某些情况外还有效:
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();
}
}
}
如果您有2月中间且开始日期是月末,则会产生不可接受的结果。例如:
来自:2013年12月31日 致:2014年12月31日
差异将产生:12个月,3天。
答案 0 :(得分:3)
答案 1 :(得分:1)
我的一位同事最终得出了正确的答案。逐步向日历添加月份的问题是您从1月31日到2月28日到3月28日,而不是3月31日。这会增加不准确性。解决方案是在原始开始日期添加1个月,2个月,3个月等。然后你从1月31日到2月28日到3月31日。无论如何,这是他的解决方案,我稍微改变了。
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();
}
}
}