【问题标题】:Summing time past 24 hours过去 24 小时的求和时间
【发布时间】:2012-07-06 01:32:01
【问题描述】:

我有以下方法来求和时间:

public static String sumTime(String date1, String date2) throws ParseException {
    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss.SSS");

    Date d1 = formatter.parse(date1);
    Date d2 = formatter.parse(date2);
    calendar.setTime(d2);

    d1 = DateUtils.addHours(d1, calendar.get(Calendar.HOUR_OF_DAY));
    d1 = DateUtils.addMinutes(d1, calendar.get(Calendar.MINUTE));
    d1 = DateUtils.addSeconds(d1, calendar.get(Calendar.SECOND));
    d1 = DateUtils.addMilliseconds(d1, calendar.get(Calendar.MILLISECOND));

    return formatter.format(d1);
}

DateUtils 来自Apache Commons Lang 3
它非常适合我想要的,除非总和大于 24 小时。


例如:

String time = "00:00:00.000";

try {
    for (int i = 0; i < 24; i++) {
            time = sumTime(time, "01:00:00.123");
    }

    System.out.println(time);
} catch (ParseException e) {
    e.printStackTrace();
}

结果是:

00:00:02.952

但这是我想要的:

24:00:02.952


有没有(简单的)方法可以做到这一点?
我不介意使用不同的库/方法,只要我得到正确的结果。


请记住,时间将始终从 00:00:00.000 开始;

【问题讨论】:

    标签: java time calendar hour


    【解决方案1】:

    您是否考虑过用天来表示每组 24 小时?您可以在 sumTime 方法中添加一些内容,并让它添加天数。 SimpleDateFormater 可以使用天数,也许这会有所帮助:

    http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html

    【讨论】:

      【解决方案2】:

      java.util.Date 在这方面没有那么强。请参阅 Joda Time 以获取正确处理此问题的库。

      我现在无权访问安装。代码将接近于此:

      DateTimeFormatter dtf = DateTimeFormat.forPattern("HH:mm:ss.SSS");
      DateTime start = dtf.parseDateTime(date1);
      DateTime end = dtf.parseDateTime(date2);
      PeriodFormatter pf = new PeriodFormatterBuilder()
       .printZeroAlways().appendHours().appendSeparator(":")
       .appendMinutes().appendSeparator(":")
       .appendSeconds().appendSeparator(":")
       .appendMillis3Digit().toFormatter();
      return pf.print(new Period(start, end, PeriodType.time()));
      

      【讨论】:

      • 您确定是否可以使用该库来完成?如果是,你能告诉我从哪里开始寻找吗?
      • 你可能需要 MutablePeriod - 你可以从那里开始 - joda-time.sourceforge.net/api-release/index.html?org/joda/time/…
      • 我对此进行了测试,并以与开始时相同的方式工作。我可能会在其他时候尝试与 Joda 再次解决这个问题,但我会选择 Chip 的解决方案。谢谢大家的帮助。
      • 抱歉,我没有指定 Period() 需要输入 Time。那是固定的。没有这个,小时数会回到零,天数会增加。当然,Chip 的解决方案是可以的,只要您能够承受测试成本,并且您没有预料到未来会出现更复杂的需求。
      • ReX,我完全同意@Gene。我建议任何一天都使用 Joda-time 来代替我的解决方案。始终使用每天被成千上万人使用/调试的库。我在回答中提到了这一点。所以,如果 Gene 的代码有效,你应该使用它。
      【解决方案3】:

      Date 不是正确使用的类。 Date 是一个瞬间,而不是“日期差异”。

      正如有人已经建议的那样,正确的做法是使用像 Joda Time 这样的库。如果您不想这样做 - 这里有一个可能的选择:

      自己将字符串解析成小时、分钟和秒,然后自己添加。

      不过,我鼓励您研究一个“广为接受”的库。在我的解决方案中可能有些事情我没有想到。此外,您还添加了所有错误检查。

      这是起始代码:

      public class TimeInterval {
      short milliSeconds;
      short seconds;
      short minutes;
      int hours;
      
      public TimeInterval (String dateString) {
          // HHHHHH:MI:SS.SSS
          Pattern pattern = Pattern.compile("(\\d+):(\\d\\d):(\\d\\d)\\.(\\d\\d\\d)");
          Matcher matcher = pattern.matcher(dateString);
          if ( matcher.find() ) {
              hours = Integer.parseInt(dateString.substring(matcher.start(1), matcher.end(1)));
              minutes = Short.parseShort(dateString.substring(matcher.start(2), matcher.end(2)));
              seconds = Short.parseShort(dateString.substring(matcher.start(3), matcher.end(3)));
              milliSeconds = Short.parseShort(dateString.substring(matcher.start(4), matcher.end(4)));
          }
      }
      
      private TimeInterval() {
      }
      
      public TimeInterval add(TimeInterval interval) {
          TimeInterval ret = new TimeInterval();
          ret.milliSeconds = (short) ((interval.milliSeconds + milliSeconds)%1000);
          int carry = (interval.milliSeconds + milliSeconds)/1000;
          ret.seconds = (short) ((interval.seconds + seconds)%60 + carry );
          carry =(interval.seconds + seconds)/60;
          ret.minutes = (short) ((interval.minutes + minutes)%60 + carry);
          carry = (interval.minutes + minutes)/60;
          ret.hours = (interval.hours + hours + carry);
          return ret;
      }
      
      @Override
      public String toString() {
          return String.format("%d:%02d:%02d.%03d", hours, minutes, seconds, milliSeconds);
      }
      }
      

      使用这个类,你的程序会是这样的:

      TimeInterval time = new TimeInterval("00:00:00.000");
      
      try {
          for (int i = 0; i < 24; i++) {
            time = time.add(new TimeInterval("01:00:00.123"));
          }
      
          System.out.println(time.toString());
      } catch (ParseException e) {
          e.printStackTrace();
      }
      

      【讨论】:

      • 您的解决方案效果很好,非常感谢。下次我可能会尝试和Joda Time一起去,但这次我没有运气。
      【解决方案4】:

      您是否尝试过实际上直接支持此类事情的 Joda-Time?

          PeriodFormatterBuilder builder = new PeriodFormatterBuilder();
          builder.printZeroAlways()
              .minimumPrintedDigits(2)
              .appendHours()
              .appendSeparator(":").appendMinutes()
              .appendSeparator(":").appendSeconds()
              .appendSeparator(".").appendMillis3Digit();
      
          PeriodFormatter formatter = builder.toFormatter();
          PeriodParser parser = builder.toParser();
      
          String s1 = "11:00:00.111";
          String s2 = "23:00:00.111";
      
          MutablePeriod p1 = new MutablePeriod();
          MutablePeriod p2 = new MutablePeriod();
          parser.parseInto(p1, s1, 0, Locale.getDefault());       
          parser.parseInto(p2, s2, 0, Locale.getDefault());       
          p1.add(p2);
      
      
          System.out.println(formatter.print(p1));
      

      打印

      34:00:00.222
      

      【讨论】:

      • 这有一个问题,如果我将两个毫秒的值都更改为 500,则会打印“34:00:00.1000”。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-28
      • 2020-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多