【问题标题】:Java Date roundingJava 日期舍入
【发布时间】:2021-09-21 06:22:24
【问题描述】:

我想要一种优雅的方式将 java Date 向上或向下舍入到最接近的分钟(或秒、小时、天)。

例如,“2012 年 1 月 25 日星期三 10:36:34 GMT”四舍五入到最接近的分钟的日期将是“2012 年 1 月 25 日星期三 10:37:00 GMT”

【问题讨论】:

标签: java


【解决方案1】:

如果您使用 Apache commons-lang,您可以使用 DateUtils 来四舍五入您的日期:

Date now = new Date();
Date nearestMinute = DateUtils.round(now, Calendar.MINUTE);

【讨论】:

  • 干杯,truncate() 对于总是向下舍入看起来也很有用
  • @guido-garcía :在 DateUtils 中不再包含“round”方法。 DateUtils 中的任何替代方法?
  • commons-lang 中 DateUtils 的随机当前版本 (2.6) 有 round()、truncate() 和 ceiling() 方法
【解决方案2】:

不使用 3rd-party 库的方法(虽然可能不那么优雅且不那么灵活):添加半个字段(以分钟为单位 - 30 秒四舍五入)并设置此字段和更低的字段归零。

Calendar calendar = ... // assume you already have it with a specified Date value

// 'add' cause changing larger fields if necessary
calendar.add( Calendar.SECOND, 30 ); 
calendar.set( Calendar.SECOND, 0 );
calendar.set( Calendar.MILLISECOND, 0 );

如果当前值小于 30 秒,则分钟值不会在“添加”时更改。否则,它将增加 1。在任何情况下,秒和更低的值都归零。所以我们进行了四舍五入。

【讨论】:

  • 谢谢,是的,避免依赖 3rd 方库很好
  • 为我工作。谢谢。
【解决方案3】:

您可以使用 Apache-commons 的DateUtils

import org.apache.commons.lang.time.FastDateFormat;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;

FastDateFormat dtFormat = DateFormatUtils.ISO_DATETIME_FORMAT;

Date now = new Date( );
Date nearestHour = DateUtils.round( now, Calendar.HOUR );
Date nearestDay = DateUtils.round( now, Calendar.DAY_OF_MONTH );
Date nearestYear = DateUtils.round( now, Calendar.YEAR );

System.out.println( "Now: " + dtFormat.format( now ) );
System.out.println( "Nearest Hour: " + dtFormat.format( nearestHour ) );
System.out.println( "Nearest Day: " + dtFormat.format( nearestDay ) );
System.out.println( "Nearest Year: " + dtFormat.format( nearestYear )

【讨论】:

    【解决方案4】:

    要使用 Apache commons-lang 向上/向下舍入,您可以使用以下方法:

    • 四舍五入使用DateUtils.ceiling(date, Calendar.HOUR)
    • 向下舍入使用DateUtils.truncate(date, Calendar.HOUR)
    • 要四舍五入到最近的单位使用DateUtils.round(date, Calendar.HOUR)

    查看示例:

        SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
    
        String sDate1 = "11-05-2019 19:01:00";
        Date date1 = formatter.parse(sDate1);
        System.out.println(DateUtils.round(date1, Calendar.HOUR));    // Sat May 11 19:00:00 MSK 2019
        System.out.println(DateUtils.truncate(date1, Calendar.HOUR)); // Sat May 11 19:00:00 MSK 2019
        System.out.println(DateUtils.ceiling(date1, Calendar.HOUR));  // Sat May 11 20:00:00 MSK 2019
    
        String sDate2 = "11-05-2019 19:29:00";
        Date date2 = formatter.parse(sDate2);
        System.out.println(DateUtils.round(date2, Calendar.HOUR));    // Sat May 11 19:00:00 MSK 2019
        System.out.println(DateUtils.truncate(date2, Calendar.HOUR)); // Sat May 11 19:00:00 MSK 2019
        System.out.println(DateUtils.ceiling(date2, Calendar.HOUR));  // Sat May 11 20:00:00 MSK 2019
    
        String sDate3 = "11-05-2019 19:30:00";
        Date date3 = formatter.parse(sDate3);
        System.out.println(DateUtils.round(date3, Calendar.HOUR));    // Sat May 11 20:00:00 MSK 2019
        System.out.println(DateUtils.truncate(date3, Calendar.HOUR)); // Sat May 11 19:00:00 MSK 2019
        System.out.println(DateUtils.ceiling(date3, Calendar.HOUR));  // Sat May 11 20:00:00 MSK 2019
    
        String sDate4 = "11-05-2019 19:31:00";
        Date date4 = formatter.parse(sDate4);
        System.out.println(DateUtils.round(date4, Calendar.HOUR));    // Sat May 11 20:00:00 MSK 2019
        System.out.println(DateUtils.truncate(date4, Calendar.HOUR)); // Sat May 11 19:00:00 MSK 2019
        System.out.println(DateUtils.ceiling(date4, Calendar.HOUR));  // Sat May 11 20:00:00 MSK 2019
    
        String sDate5 = "11-05-2019 19:59:00";
        Date date5 = formatter.parse(sDate5);
        System.out.println(DateUtils.round(date5, Calendar.HOUR));    // Sat May 11 20:00:00 MSK 2019
        System.out.println(DateUtils.truncate(date5, Calendar.HOUR)); // Sat May 11 19:00:00 MSK 2019
        System.out.println(DateUtils.ceiling(date5, Calendar.HOUR));  // Sat May 11 20:00:00 MSK 2019
    

    【讨论】:

      【解决方案5】:

      最好的解决方案是使用来自 Apache commons 的 DateUtils。 但是,如果您想避免导入它们,这将是 Java 中的解决方案。不确定这是否符合“优雅的解决方案”的意思。

      /** 
            Takes given date and returns date rounded to nearest  minute
      */
      public Date roundToMin(Date d){
          Calendar date = new GregorianCalendar();
          date.setTime(d);
          int deltaMin = date.get(Calendar.SECOND)/30;
      
          date.set(Calendar.SECOND, 0);
          date.set(Calendar.MILLISECOND, 0);
          date.add(Calendar.MINUTE, deltaMin);
      
          return date.getTime();
      }
      

      【讨论】:

        【解决方案6】:

        如果我可以使用纯 Java 实现这一点,我会尽量不使用额外的库:

         new Date( ((new Date().getTime() + 500) / 1000) * 1000 )
        

        【讨论】:

        • @Andy897 如果毫秒数小于 500,则向下取整(下限),如果毫秒数大于 500,则向上取整(上限)。在此示例中,我展示了四舍五入到秒。虽然我建议您最好为此使用 Java 8 Time API
        【解决方案7】:

        如果您需要对分钟进行四舍五入,您可以这样做, int 分钟 = 分钟 - (分钟 % n);

        如果想将分钟四舍五入,则 n = 5。

        【讨论】:

          【解决方案8】:

          这是一个 Java8+ 的答案:

          public static Instant roundHalfUp(Instant instant, TemporalUnit unit) {
              return instant.plus(unit.getDuration().dividedBy(2))
                      .truncatedTo(unit);
          }
          

          将日期舍入到分钟,使用日期-> 即时-> 日期转换:

          Date.from(roundHalfUp(date.toInstant(), ChronoUnit.MINUTES))
          

          【讨论】:

            【解决方案9】:

            添加 commons-lang jar 只是为了对日期进行舍入不是一个好主意,我更喜欢这个功能:

            public static Date round(Date d) {
                try {
                    SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");
                    return sdf.parse(sdf.format(d));
                } catch (ParseException ex) {
                    //This exception will never be thrown, because sdf parses what it   formats
                    return d;
                }
            }
            

            【讨论】:

            • 我见过的最奇怪的 try catch 块用法:o
            • 简单,对象 SimpleDateFormat 必须能够解析它的格式。 ParseException 永远不会被抛出,捕获它是非常安全的:-)
            • 我认为这是错误的。它不会四舍五入到最近的一天,而是到前一天中最近的一天。即 09/11/2017 23:59 您的代码返回 09/11/2017 而不是 10/11/2017
            • 是的,我知道他想要最近的一分钟,甚至不是一天。
            【解决方案10】:

            在以下函数“roundBy”中,可以选择按秒/分钟/小时/天对日期进行四舍五入。
            这可能不准确,但想法很清楚,希望

            public static final long MILLISECONDS_IN_SECOND = (long)(1000);
            public static final long MILLISECONDS_IN_MINUTE = (MILLISECONDS_IN_SECOND * 60);
            public static final long MILLISECONDS_IN_HOUR = (MILLISECONDS_IN_MINUTE * 60);
            public static final long MILLISECONDS_IN_DAY = (MILLISECONDS_IN_HOUR * 24);
            
            public synchronized static Date roundBy(Date date, long UNIT) {
                long time = date.getTime();
                long timeOutOfUnit= time % UNIT;
                time -= timeOutOfUnit;
                if(timeOutOfUnit >= (UNIT / 2)) {
                    time += UNIT;
                }
                return new Date(time);
            }
            

            【讨论】:

              【解决方案11】:
                 //How about if we represent the window to round to in Duration
                 // like this
                 Duration duration = Duration.of(14, ChronoUnit.MINUTES);
              
              
                 // example of any time
                 ZonedDateTime time = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));
                 long s = duration.getSeconds();
                 long st = time.toEpochSecond();
                 st = st - st%s;
              
                 time = ZonedDateTime.ofInstant(Instant.ofEpochSecond(st), time.getZone());
              
                 // this trims the nanos and round to secons
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2014-05-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多