【问题标题】:Calculate date/time difference in java [duplicate]在java中计算日期/时间差[重复]
【发布时间】:2011-07-18 02:42:51
【问题描述】:

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

我的代码有点小问题:

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.

谁能看到我在这里做错了什么?

【问题讨论】:

标签: java time


【解决方案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); 

【讨论】:

  • @Mark 我不同意。你错过了问题的重点。尽管他在帖子的其余部分中使用了“以秒为单位的时间”这个短语,但他明确表示他实际上并不想要简单的转换,他想要余数。这比公认的答案效率低(使用方法调用,即使在 JVM 字节码中也是一些指令),不太清楚(它更长,坦率地说,如果在那种情况下发现“1000”或“60”是幻数,他们没有使用完整的套牌),而且关键的是,它并没有达到 OP 想要的效果。
  • 有一种方法可以为此编写通用方法。见stackoverflow.com/a/10650881/82609
  • 如果我愿意,相差几周、几个月、几年?
  • @jose920405 在这种情况下,你需要 Joda 时间
  • 这将给出 OP 指定的他们不想要的答案。
【解决方案2】:

试试

long diffSeconds = diff / 1000 % 60;  
long diffMinutes = diff / (60 * 1000) % 60; 
long diffHours = diff / (60 * 60 * 1000);

注意:这里假设 diff 是非负数。

【讨论】:

  • @vels4j 我假设我刚刚添加的原始代码的第三行。感谢您指出这一点。
  • diffMinutes 仍然是错误的
  • @vels4j 以什么方式?
  • 我已经更新了答案,请检查一下。澄清后放弃我的编辑
  • @vels4j 你说哪一个是错误的,因为 6 似乎是正确的答案,因为你在 OPs 问题中也有几个小时。
【解决方案3】:

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

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

计算间隔示例:

Seconds.between(startDate, endDate);
Days.between(startDate, endDate);

【讨论】:

  • 请注意,如果您正在处理 2 个 java.util.Date 对象,那么您需要使用 Days.daysBetween(LocalDate.fromDateFields(startDate), LocalDate.fromDateFields(endDate));
  • 我已经创建了一个如何使用 Joda 时间的示例:stackoverflow.com/a/15541322/562769
  • 目前的做法是什么? (使用 JSR-310)
【解决方案4】:

从 Java 5 开始,您可以使用 java.util.concurrent.TimeUnit 来避免在代码中使用像 1000 和 60 这样的幻数。

顺便说一句,您应该注意计算闰秒:一年的最后一分钟可能会有一个额外的闰秒,因此它确实持续了 61 秒,而不是预期的 60 秒。 ISO 规范甚至计划可能为 61 秒。您可以在java.util.Datejavadoc 中找到详细信息。

【讨论】:

  • 除非有很好的商业理由来包含这些杂散的闰秒,否则您可以将它们视为一种有趣但无关紧要的科学好奇心。
  • 我同意“闰秒”是一个小技巧。但是夏令时或时区差异呢?
  • @YvesMartin "时区差异" 看看他的日期格式。时区没有地方。如果他确实希望这可以跨时区工作,他会遇到更大的问题。不过,夏令时是个问题。
  • «它确实持续了 60 秒而不是预期的 59 秒» 您的意思是它持续了 61 秒 (0..60) 而不是预期的 60 秒 (0..59)。 ;)
  • 修正了我的评论...一个经典的纠察队/间距问题!谢谢指点
【解决方案5】:

试试这个以友好地表示时间差(以毫秒为单位):

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

【讨论】:

  • 在线long diffYears = (long) (timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 365));你需要稍后再投 long,否则除数是 int 并且溢出:diffYears = (timeDifferenceMilliseconds / ((long)60 * 60 * 1000 * 24 * 365));
  • 我已经修复了代码
【解决方案6】:

这基本上是一个数学问题,而不是一个 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;

【讨论】:

    【解决方案7】:

    这是一个建议,使用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

    【讨论】:

      【解决方案8】:

      我知道这是一个老问题,但我最终做了一些与接受的答案略有不同的事情。人们谈论 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是一个被高度忽视的类。

      【讨论】:

      • 谢谢!我也是这么想的,但你加快了速度:)
      【解决方案9】:

      使用您作为构造函数的时间差异创建一个Date 对象,
      然后使用 Calendar 方法获取值..

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

      【讨论】:

      • 不推荐使用这些方法。
      • 工作正常,但你不能忘记设置时区:Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
      【解决方案10】:

      difference-between-two-dates-in-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;
          }
      }
      

      【讨论】:

      • 好。时间偏移很重要 - 即使差异是基于相同的偏移计算的,但两个“日历日期”之间的任何夏令时差异也会对结果产生影响。您应该使用 java.util.concurrent.TimeUnit 作为常量。
      【解决方案11】:
      // 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.");
      

      【讨论】:

        【解决方案12】:

        乔达时间

        Joda-Time 2.3 库为这项杂务提供了已经调试过的代码。

        Joad-Time 包括三个类来表示时间跨度:PeriodIntervalDurationPeriod 将跨度跟踪为月数、天数、小时数等(与时间线无关)。

        // © 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
        

        【讨论】:

          【解决方案13】:

          这是我的代码。

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

          【讨论】:

            【解决方案14】:

            long diffSeconds = (diff / 1000)%60;
            试试这个,让我知道它是否正常工作......

            【讨论】:

              【解决方案15】:

              好吧,我再试试另一个代码示例:

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

              【讨论】:

                【解决方案16】:
                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)

                【讨论】:

                  【解决方案17】:

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

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

                  【讨论】:

                  • 这将失败,时间单位分钟和时间差异超过一小时
                  猜你喜欢
                  • 1970-01-01
                  • 2013-10-09
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-02-18
                  • 1970-01-01
                  相关资源
                  最近更新 更多