【问题标题】:How to format time intervals in Java?如何在 Java 中格式化时间间隔?
【发布时间】:2012-04-13 15:47:01
【问题描述】:

我创建 J2SE 应用程序,该应用程序需要将两次以毫秒为单位的时间格式化成一个字符串,表示这两次之间的间隔。

long time1 = 1334331041677L; //Fri Apr 13 17:30:41 CEST 2012
long time2 = time1+1000*60*2; //Fri Apr 13 17:32:41 CEST 2012

我想得到类似“00:02:00”的东西。这很简单,但我需要格式化从几秒到几年的间隔 - 所以库应该处理它。理想情况下,如果这个库可以根据国家的习惯(如果有的话)格式化间隔。

我已经搜索了问题和答案,我的解决方案可能是来自 Apache Commons 的 Jodatime 或 Lang 库。您能给我一些建议吗?这些库中的哪个库可以更好地解决我的要求?提前谢谢你。

【问题讨论】:

    标签: java format intervals


    【解决方案1】:

    PeriodFormat in Joda Time 可能是你想要的 - 但你需要非常仔细考虑你想如何格式化超过一个天。请记住,月份和年份的长度是可变的 - 如果您乐于将最大的单位作为一天,那可能会让事情变得简单。

    您还应该注意Period(可以包括“月”之类的内容)和Duration(固定毫秒数)之间的 Joda Time 差异。两者之间的规范化恰好涉及上述问题 :) 基本上,您应该弄清楚您是否对两个瞬间之间经过的时间差异感兴趣,或者“日历”的差异两个本地日期/时间值之间的时间。例如,在特定时区的特定日期的午夜和凌晨 2 点之间可能是 1 小时、2 小时或 3 小时的经过时间......

    【讨论】:

    • 1) 我尽我所能搜索了 Jogatime API,但是当大于 24 小时时,我找不到以正确方式获取格式化值的方法。例如。如果差值为 2 天 3 小时 12 分钟 10 秒,则应返回“51:12:10”而不是“02:03:12:10”。 2)实际格式正确的时间间隔是多少? “51:12:10”还是“02:03:12:10”?它是解决某种处方还是取决于每个程序员的需求?
    • @user1315357:“正确”是什么意思?这完全取决于你想要什么。但是您应该能够让PeriodFormat 做您想做的事情 - 您应该构建周期以仅使用您想要的单位。如果没有看到您尝试的代码,很难说出您做错了什么。
    【解决方案2】:

    您可以将标准 Java Calendar 用于最多一天(24 小时)的时间间隔。但是,无法在更长的时间内(几天,几年)使用此技巧...

    long start = System.currentTimeMillis();
    /*
     * perform the measured activity here,
     * let's say it will take 2 minutes 5 seconds => 125 seconds => 125000ms
     */
    Thread.sleep(125 * 1000);
    long stop = System.currentTimeMillis();
    Calendar c = Calendar.getInstance();
    c.set(Calendar.HOUR_OF_DAY, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MILLISECOND, 0);
    c.setTimeInMillis(c.getTimeInMillis() + (stop - start));
    DateFormat df = new SimpleDateFormat("HH:mm:ss.SSS");
    System.out.println(df.format(c.getTime()));
    

    【讨论】:

      【解决方案3】:

      如果我理解正确,以下(使用 Joda Time)应该会有所帮助

      import org.joda.time.DateTime;
      import org.joda.time.Period;
      
      private String formatDuration(DateTime dt1, DateTime dt2) {
        Period period = new Period(dt1, dt2);
        String str = String.format("%s:%02d:%02d:%02d:%02d:%02d", 
          period.getYears(), period.getMonths(), period.getDays(), 
          period.getHours(), period.getMinutes(), period.getSeconds());
          // Ignoring milliseconds
      
        String[] tokens = str.split(":");
        boolean currNonZero = false, flag = false, isFirst = true;
        int ctr = 0, pos = 0;
        StringBuilder sb = new StringBuilder();
        for (String token : tokens) {
          pos++;
          int val = Integer.parseInt(token);
          currNonZero = (val > 0);
          if ((ctr < 3 && (flag || currNonZero)) || (ctr == 0 && pos > 3)) {
            if (isFirst) { isFirst = false; }
            else { sb.append(":"); }
            sb.append(token);
            flag = (++ctr < 3);
          }
        }
      
        return sb.toString();  
      }
      

      一些测试,

      DateTime dt1 = new DateTime(2012, 1, 1, 8, 3, 5, 0);
      DateTime dt2 = new DateTime(2012, 1, 2, 9, 5, 6, 0);
      DateTime dt3 = new DateTime(2012, 2, 3, 11, 3, 5, 0);
      DateTime dt4 = new DateTime(2012, 2, 3, 11, 3, 10, 0);
      DateTime dt5 = new DateTime(2012, 2, 3, 11, 3, 10, 5); //5 millis away from dt4
      
      formatDuration(dt1, dt2); // Returns "01:01:01"
      formatDuration(dt1, dt3); // Returns "01:02:03"
      formatDuration(dt3, dt4); // Returns "00:00:05"
      formatDuration(dt4, dt5); // Returns "00:00:00"
      

      【讨论】:

      • 谢谢,我会尽量找一些不那么难的。
      【解决方案4】:

      根据this answer,这是格式化经过时间的最有效方法:

      public static String combinationFormatter(final long millis) {
          long seconds = TimeUnit.MILLISECONDS.toSeconds(millis)
                  - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis));
          long minutes = TimeUnit.MILLISECONDS.toMinutes(millis)
                  - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis));
          long hours = TimeUnit.MILLISECONDS.toHours(millis);
      
          StringBuilder b = new StringBuilder();
          b.append(hours == 0 ? "00" : hours < 10 ? String.valueOf("0" + hours) : 
          String.valueOf(hours));
          b.append(":");
          b.append(minutes == 0 ? "00" : minutes < 10 ? String.valueOf("0" + minutes) : 
          String.valueOf(minutes));
              b.append(":");
          b.append(seconds == 0 ? "00" : seconds < 10 ? String.valueOf("0" + seconds) : 
          String.valueOf(seconds));
          return b.toString(); 
       }
      

      【讨论】:

        【解决方案5】:

        详细回答:https://stackoverflow.com/a/39600534/5330578

        经过时间少于 24 小时的简单格式化。超过 24 小时,代码将仅显示第二天的小时数,不会将经过的日期添加到小时数中。

        public static String formatElapsedTime(long milliseconds) {
        
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        
            return sdf.format(milliseconds);
        }
        

        【讨论】:

          猜你喜欢
          • 2011-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-17
          • 1970-01-01
          • 2015-02-10
          相关资源
          最近更新 更多