计算java中的日期/时间差异
我想计算两个日期之间的差异,以小时/分钟/秒为单位。
我的代码在这里有一个小问题:
String dateStart = "11/03/14 09:29:58"; String dateStop = "11/03/14 09:33:43"; // Custom date format SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); Date d1 = null; Date d2 = null; try { d1 = format.parse(dateStart); d2 = format.parse(dateStop); } catch (ParseException e) { e.printStackTrace(); } // Get msec from each, and subtract. long diff = d2.getTime() - d1.getTime(); long diffSeconds = diff / 1000; long diffMinutes = diff / (60 * 1000); long diffHours = diff / (60 * 60 * 1000); System.out.println("Time in seconds: " + diffSeconds + " seconds."); System.out.println("Time in minutes: " + diffMinutes + " minutes."); System.out.println("Time in hours: " + diffHours + " hours.");
这应该会产生:
Time in seconds: 45 seconds. Time in minutes: 3 minutes. Time in hours: 0 hours.
但是我得到这个结果:
Time in seconds: 225 seconds. Time in minutes: 3 minutes. Time in hours: 0 hours.
任何人都可以看到我在这里做错了吗?
尝试
long diffSeconds = diff / 1000 % 60; long diffMinutes = diff / (60 * 1000) % 60;
我宁愿使用建议的java.util.concurrent.TimeUnit
类。
long diff = d2.getTime() - d1.getTime();//as given long seconds = TimeUnit.MILLISECONDS.toSeconds(diff); long minutes = TimeUnit.MILLISECONDS.toMinutes(diff);
如果你能够使用外部库,我建议你使用Joda-Time ,注意到:
Joda-Time是Java SE 8之前Java事实上的标准日期和时间库。现在要求用户迁移到java.time(JSR-310)。
计算之间的示例:
Seconds.between(startDate, endDate); Days.between(startDate, endDate);
从Java 5开始,您可以使用java.util.concurrent.TimeUnit
来避免在代码中使用Magic Numbers(如1000和60)。
顺便说一下,你应该注意闰秒计算:一年的最后一分钟可能会有一个额外的闰秒,所以它确实持续61秒,而不是预期的60秒。 ISO规范甚至计划可能61秒。 您可以在java.util.Date
javadoc中找到详细信息。
试试这个友好的时间表示形式(以毫秒为单位):
String friendlyTimeDiff(long timeDifferenceMilliseconds) { long diffSeconds = timeDifferenceMilliseconds / 1000; long diffMinutes = timeDifferenceMilliseconds / (60 * 1000); long diffHours = timeDifferenceMilliseconds / (60 * 60 * 1000); long diffDays = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24); long diffWeeks = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 7); long diffMonths = (long) (timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 30.41666666)); long diffYears = timeDifferenceMilliseconds / ((long)60 * 60 * 1000 * 24 * 365); if (diffSeconds < 1) { return "less than a second"; } else if (diffMinutes < 1) { return diffSeconds + " seconds"; } else if (diffHours < 1) { return diffMinutes + " minutes"; } else if (diffDays < 1) { return diffHours + " hours"; } else if (diffWeeks < 1) { return diffDays + " days"; } else if (diffMonths < 1) { return diffWeeks + " weeks"; } else if (diffYears < 1) { return diffMonths + " months"; } else { return diffYears + " years"; } }
这基本上是一个数学问题,而不是一个java问题。
您收到的结果是正确的。 这是因为225秒是3分钟(当进行积分时)。 你想要的是这样的:
- 除以1000得到秒数 – >休息是毫秒
- 除以60得到分钟数 – >休息是秒
- 除以60得到小时数 – >休息是分钟
或者在java中:
int millis = diff % 1000; diff/=1000; int seconds = diff % 60; diff/=60; int minutes = diff % 60; diff/=60; hours = diff;
差之间,两日式的Java
从链接中提取代码
public class TimeDiff { /** * (For testing purposes) * */ public static void main(String[] args) { Date d1 = new Date(); try { Thread.sleep(750); } catch(InterruptedException e) { /* ignore */ } Date d0 = new Date(System.currentTimeMillis() - (1000*60*60*24*3)); // About 3 days ago long[] diff = TimeDiff.getTimeDifference(d0, d1); System.out.printf("Time difference is %d day(s), %d hour(s), %d minute(s), %d second(s) and %d millisecond(s)\n", diff[0], diff[1], diff[2], diff[3], diff[4]); System.out.printf("Just the number of days = %d\n", TimeDiff.getTimeDifference(d0, d1, TimeDiff.TimeField.DAY)); } /** * Calculate the absolute difference between two Date without * regard for time offsets * * @param d1 Date one * @param d2 Date two * @param field The field we're interested in out of * day, hour, minute, second, millisecond * * @return The value of the required field */ public static long getTimeDifference(Date d1, Date d2, TimeField field) { return TimeDiff.getTimeDifference(d1, d2)[field.ordinal()]; } /** * Calculate the absolute difference between two Date without * regard for time offsets * * @param d1 Date one * @param d2 Date two * @return The fields day, hour, minute, second and millisecond */ public static long[] getTimeDifference(Date d1, Date d2) { long[] result = new long[5]; Calendar cal = Calendar.getInstance(); cal.setTimeZone(TimeZone.getTimeZone("UTC")); cal.setTime(d1); long t1 = cal.getTimeInMillis(); cal.setTime(d2); long diff = Math.abs(cal.getTimeInMillis() - t1); final int ONE_DAY = 1000 * 60 * 60 * 24; final int ONE_HOUR = ONE_DAY / 24; final int ONE_MINUTE = ONE_HOUR / 60; final int ONE_SECOND = ONE_MINUTE / 60; long d = diff / ONE_DAY; diff %= ONE_DAY; long h = diff / ONE_HOUR; diff %= ONE_HOUR; long m = diff / ONE_MINUTE; diff %= ONE_MINUTE; long s = diff / ONE_SECOND; long ms = diff % ONE_SECOND; result[0] = d; result[1] = h; result[2] = m; result[3] = s; result[4] = ms; return result; } public static void printDiffs(long[] diffs) { System.out.printf("Days: %3d\n", diffs[0]); System.out.printf("Hours: %3d\n", diffs[1]); System.out.printf("Minutes: %3d\n", diffs[2]); System.out.printf("Seconds: %3d\n", diffs[3]); System.out.printf("Milliseconds: %3d\n", diffs[4]); } public static enum TimeField {DAY, HOUR, MINUTE, SECOND, MILLISECOND; } }
使用时间之间的差异作为构造函数创建一个Date
对象,
然后使用日历方法来获取值..
Date diff = new Date(d2.getTime() - d1.getTime()); Calendar calendar = Calendar.getInstance(); calendar.setTime(diff); int hours = calendar.get(Calendar.HOUR_OF_DAY); int minutes = calendar.get(Calendar.MINUTE); int seconds = calendar.get(Calendar.SECOND);
// d1, d2 are dates long diff = d2.getTime() - d1.getTime(); long diffSeconds = diff / 1000 % 60; long diffMinutes = diff / (60 * 1000) % 60; long diffHours = diff / (60 * 60 * 1000) % 24; long diffDays = diff / (24 * 60 * 60 * 1000); System.out.print(diffDays + " days, "); System.out.print(diffHours + " hours, "); System.out.print(diffMinutes + " minutes, "); System.out.print(diffSeconds + " seconds.");
乔达时间
Joda-Time 2.3库为这个杂项提供了已经调试好的代码。
Joad-Time包括三个类来表示一段时间: Period
, Interval
和Duration
。 Period
跟踪一个跨度的月数,天数,小时数等(不受时间线限制)。
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so. // Specify a time zone rather than rely on default. // Necessary to handle Daylight Saving Time (DST) and other anomalies. DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" ); DateTimeFormatter formatter = DateTimeFormat.forPattern( "yy/MM/dd HH:mm:ss" ).withZone( timeZone ); DateTime dateTimeStart = formatter.parseDateTime( "11/03/14 09:29:58" ); DateTime dateTimeStop = formatter.parseDateTime( "11/03/14 09:33:43" ); Period period = new Period( dateTimeStart, dateTimeStop ); PeriodFormatter periodFormatter = PeriodFormat.getDefault(); String output = periodFormatter.print( period ); System.out.println( "output: " + output );
当运行…
output: 3 minutes and 45 seconds
这是一个建议,使用TimeUnit
来获取每个时间部分并格式化它们。
private static String formatDuration(long duration) { long hours = TimeUnit.MILLISECONDS.toHours(duration); long minutes = TimeUnit.MILLISECONDS.toMinutes(duration) % 60; long seconds = TimeUnit.MILLISECONDS.toSeconds(duration) % 60; long milliseconds = duration % 1000; return String.format("%02d:%02d:%02d,%03d", hours, minutes, seconds, milliseconds); } SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss,SSS"); Date startTime = sdf.parse("01:00:22,427"); Date now = sdf.parse("02:06:38,355"); long duration = now.getTime() - startTime.getTime(); System.out.println(formatDuration(duration));
结果是:01:06:15,928
这是我的代码。
import java.util.Date; // to calculate difference between two days public class DateDifference { // to calculate difference between two dates in milliseconds public long getDateDiffInMsec(Date da, Date db) { long diffMSec = 0; diffMSec = db.getTime() - da.getTime(); return diffMSec; } // to convert Milliseconds into DD HH:MM:SS format. public String getDateFromMsec(long diffMSec) { int left = 0; int ss = 0; int mm = 0; int hh = 0; int dd = 0; left = (int) (diffMSec / 1000); ss = left % 60; left = (int) left / 60; if (left > 0) { mm = left % 60; left = (int) left / 60; if (left > 0) { hh = left % 24; left = (int) left / 24; if (left > 0) { dd = left; } } } String diff = Integer.toString(dd) + " " + Integer.toString(hh) + ":" + Integer.toString(mm) + ":" + Integer.toString(ss); return diff; } }
我知道这是一个古老的问题,但我最终做了一些与接受的答案略有不同的东西。 人们谈论TimeUnit
类,但没有任何答案使用OP的方式需要它的方式。
所以这是另一个解决方案,如果有人来错过它;-)
public class DateTesting { public static void main(String[] args) { String dateStart = "11/03/14 09:29:58"; String dateStop = "11/03/14 09:33:43"; // Custom date format SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); Date d1 = null; Date d2 = null; try { d1 = format.parse(dateStart); d2 = format.parse(dateStop); } catch (ParseException e) { e.printStackTrace(); } // Get msec from each, and subtract. long diff = d2.getTime() - d1.getTime(); long days = TimeUnit.MILLISECONDS.toDays(diff); long remainingHoursInMillis = diff - TimeUnit.DAYS.toMillis(days); long hours = TimeUnit.MILLISECONDS.toHours(remainingHoursInMillis); long remainingMinutesInMillis = remainingHoursInMillis - TimeUnit.HOURS.toMillis(hours); long minutes = TimeUnit.MILLISECONDS.toMinutes(remainingMinutesInMillis); long remainingSecondsInMillis = remainingMinutesInMillis - TimeUnit.MINUTES.toMillis(minutes); long seconds = TimeUnit.MILLISECONDS.toSeconds(remainingSecondsInMillis); System.out.println("Days: " + days + ", hours: " + hours + ", minutes: " + minutes + ", seconds: " + seconds); } }
尽管只是自己计算差异是可以做到的,但是这样做并不是很有意义,我认为TimeUnit
是一个高度被忽视的类。
long diffSeconds =(diff / 1000)%60;
试试这个,让我知道如果它工作正常…
那么,我会尝试另一个代码示例:
/** * Calculates the number of FULL days between to dates * @param startDate must be before endDate * @param endDate must be after startDate * @return number of day between startDate and endDate */ public static int daysBetween(Calendar startDate, Calendar endDate) { long start = startDate.getTimeInMillis(); long end = endDate.getTimeInMillis(); // It's only approximation due to several bugs (@see java.util.Date) and different precision in Calendar chosen // by user (ex. day is time-quantum). int presumedDays = (int) TimeUnit.MILLISECONDS.toDays(end - start); startDate.add(Calendar.DAY_OF_MONTH, presumedDays); // if we still didn't reach endDate try it with the step of one day if (startDate.before(endDate)) { startDate.add(Calendar.DAY_OF_MONTH, 1); ++presumedDays; } // if we crossed endDate then we must go back, because the boundary day haven't completed yet if (startDate.after(endDate)) { --presumedDays; } return presumedDays; }
Date startTime = new Date(); //... //... lengthy jobs //... Date endTime = new Date(); long diff = endTime.getTime() - startTime.getTime(); String hrDateText = DurationFormatUtils.formatDuration(diff, "d 'day(s)' H 'hour(s)' m 'minute(s)' s 'second(s)' "); System.out.println("Duration : " + hrDateText);
您可以使用Apache Commons Duration Format Utils 。 它的格式就像SimpleDateFormatter
输出:
0 days(s) 0 hour(s) 0 minute(s) 1 second(s)
如前所述 – 认为这是一个很好的答案
/** * @param d2 the later date * @param d1 the earlier date * @param timeUnit - Example Calendar.HOUR_OF_DAY * @return */ public static int getTimeDifference(Date d2,Date d1, int timeUnit) { Date diff = new Date(d2.getTime() - d1.getTime()); Calendar calendar = Calendar.getInstance(); calendar.setTime(diff); int hours = calendar.get(Calendar.HOUR_OF_DAY); int minutes = calendar.get(Calendar.MINUTE); int seconds = calendar.get(Calendar.SECOND); if(timeUnit==Calendar.HOUR_OF_DAY) return hours; if(timeUnit==Calendar.MINUTE) return minutes; return seconds; }