用java计算日期/时间差

用java计算日期/时间差,java,time,Java,Time,我想以小时/分/秒为单位计算两个日期之间的差异 我的代码有一个小问题,这里是: 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

我想以小时/分/秒为单位计算两个日期之间的差异

我的代码有一个小问题,这里是:

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; 
long diffHours = diff / (60 * 60 * 1000);

注意:这假设
diff
为非负。

如果您能够使用外部库,我建议您使用,注意:

Joda Time是JavaSE8之前的Java事实上的标准日期和时间库。现在要求用户迁移到java.time(JSR-310)

计算之间的示例:

Seconds.between(startDate, endDate);
Days.between(startDate, endDate);
长diff秒=(diff/1000)%60
试试这个,让我知道它是否正常工作…

从链接中提取代码

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;
    }
}

这基本上是一个数学问题,而不是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;
自Java5以来,您可以使用避免在代码中使用像1000和60这样的幻数

顺便说一句,你应该在计算中注意闰秒:一年中的最后一分钟可能会有一个额外的闰秒,因此它确实持续61秒,而不是预期的60秒。国际标准化组织的规范甚至可能需要61秒。您可以在javadoc中找到详细信息。

这是我的代码

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;

}
}

使用时间差作为构造函数创建一个
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);

请尝试此操作以获得时间差的友好表示形式(以毫秒为单位):

String-friendlyTimeDiff(长时间差毫秒){
long diffSeconds=时间差毫秒/1000;
long diffMinutes=时间差毫秒/(60*1000);
长时间差小时=时间差毫秒/(60*60*1000);
长差异天数=时间差异毫秒/(60*60*1000*24);
长差异周=时间差异毫秒/(60*60*1000*24*7);
长diffMonths=(长)(时差毫秒/(60*60*1000*24*30.416666));
long diffYears=时差毫秒/((长)60*60*1000*24*365);
如果(秒<1){
返回“不到一秒”;
}else if(diffMinutes<1){
返回diffSeconds+“seconds”;
}否则如果(小时数<1){
返回diffMinutes+“minutes”;
}否则如果(diffDays<1){
返回时间+小时数;
}否则如果(周数<1){
返回天数+“天”;
}否则如果(月数<1){
返回diffWeeks+“weeks”;
}否则如果(年<1){
返回月数+月数;
}否则{
返回年数+年数;
}
}

我更喜欢使用建议的
java.util.concurrent.TimeUnit

long diff = d2.getTime() - d1.getTime();//as given

long seconds = TimeUnit.MILLISECONDS.toSeconds(diff);
long minutes = TimeUnit.MILLISECONDS.toMinutes(diff); 

好的,我将尝试另一个代码示例:

/**
 * 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;
}
乔达时间 2.3库为这项工作提供了已经调试过的代码

Joad Time包括三个类来表示时间跨度:,
间隔
,和
持续时间
<代码>期间以月、日、小时等为单位跟踪跨度(与时间线无关)

/©2013巴西尔布尔克。此源代码可以由任何对此承担全部责任的人自由使用。
//指定时区,而不是依赖默认值。
//必须处理夏令时(DST)和其他异常情况。
DateTimeZone timeZone=DateTimeZone.forID(“美国/蒙特利尔”);
DateTimeFormatter formatter=DateTimeFormat.forPattern(“yy/MM/dd HH:MM:ss”)。带时区;
DateTime dateTimeStart=formatter.parseDateTime(“11/03/14 09:29:58”);
DateTime dateTimeStop=formatter.parseDateTime(“11/03/14 09:33:43”);
期间=新期间(dateTimeStart、dateTimeStop);
PeriodFormatter PeriodFormatter=PeriodFormat.getDefault();
字符串输出=periodFormatter.print(句点);
System.out.println(“输出:”+输出);
当运行时

输出:3分45秒

您可以使用。它的格式像

输出:


0天0小时0分钟1秒

如前所述-认为这是一个好答案

/**
 * @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;
 }

我知道这是一个老问题,但我最终做了一些与公认答案略有不同的事情。人们谈论
时间单位
类,但没有人按照OP想要的方式使用它

所以这里有另一个解决方案,如果有人错过了;-)


虽然自己计算差异是可以做到的,但这样做并不是很有意义,我认为
TimeUnit
是一个被高度忽略的类。

这里有一个建议,使用
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:15928

发现了一个类似的问题:有一个更好的方法:对于Java 8+有一个非常简单的方法:请注意,如果您处理的是2个Java.util.Date对象,那么您需要使用Days.daysBetween(LocalDate.fromDateFields(startDate),LocalDate.fromDateFields(endDate));我已经创建了一个如何使用Joda时间的示例:当前的方法是什么?(对于JSR-310)这些方法已被弃用。工作正常,但您不能忘记设置时区:
Calendar Calendar=Calendar.getInstance(TimeZone.getTimeZone(“UTC”)除非有很好的商业理由将这些离奇的闰秒包括在内,否则你可以将它们视为一种有趣但非实质性的科学好奇心。我同意“闰秒”只是一个小把戏。但是,如何节省日光或时区差异呢?@YvesMartin“时区差异”看看他的日期格式。
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);
/**
 * @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;
 }
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);
    }
}
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));