Java日期舍入

Java日期舍入,java,Java,我想要一种优雅的方式将java日期向上或向下舍入到最近的分钟(或秒、小时、天) 例如,将日期“Wed Jan 25 10:36:34 GMT 2012”四舍五入到最近的一分钟将是“Wed Jan 25 10:37:00 GMT 2012”如果使用Apache,您可以: 您可以使用apachecommons'DateUtils import org.apache.commons.lang.time.FastDateFormat; import org.apache.commons.lang.tim

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

例如,将日期“Wed Jan 25 10:36:34 GMT 2012”四舍五入到最近的一分钟将是“Wed Jan 25 10:37:00 GMT 2012”

如果使用Apache,您可以:


您可以使用apachecommons'
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 )

没有第三方库的方法(可能不是很优雅,也不是很灵活):添加半个字段(四舍五入为分钟-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。在任何情况下,秒和更低的值都会归零。所以我们有一个取整。

最好的解决方案是使用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();
}

如果我能用纯Java实现这一点,我会尽量不使用其他库:

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

添加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;
    }
}
在以下功能“取整”中,可以选择按秒/分钟/小时/天取整日期。
这可能不准确,但想法是明确的,希望如此


要使用Apache commons lang向上/向下取整,可以使用以下方法:

  • 使用
    DateUtils.天花(日期、日历、小时)
  • 要向下取整,请使用
    DateUtils.truncate(日期、日历、小时)
  • 要舍入到最近的单位,请使用
    DateUtils.round(日期、日历、小时)
见示例:

    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

如果你需要计算分钟数,你可以通过, 整数分钟=分钟-(分钟%n)


如果想将分钟数四舍五入为5,那么n=5。

这里有一个Java8+答案:

   //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
public static Instant roundHalfUp(Instant instant, TemporalUnit unit) {
    return instant.plus(unit.getDuration().dividedBy(2))
            .truncatedTo(unit);
}
要使用日期->即时->日期转换将日期舍入到分钟:

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

JodaTime?()这也可能有用:JodaTime不提供此功能。使用日历提取字段值,然后进行减法/加法,感觉太难看了。干杯,truncate()对于总是四舍五入也很有用down@guido-加西亚:DateUtils中不再包含“round”方法。在DateUtils中有没有其他方法可以代替综述?谢谢,是的,避免依赖第三方库对我来说很好。谢谢。我见过的try-catch块最奇怪的用法是:oSimple,对象SimpleDateFormat必须能够解析它的格式。ParseException永远不会被抛出,捕获它是非常安全的:-)我认为它是错误的。它不是取整到最近的一天,而是取整到前几天中最近的一天。i、 e.2017年11月9日23:59您的代码返回2017年11月9日,而不是2017年11月10日是的,我知道他想要的是最近的一分钟,甚至不是一天。@Andy897如果毫秒数小于500,则是四舍五入(地板),四舍五入(上限)毫秒数大于500。在本例中,我将舍入显示为秒。尽管我建议您最好使用Java8时间API来实现这一点
   //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
public static Instant roundHalfUp(Instant instant, TemporalUnit unit) {
    return instant.plus(unit.getDuration().dividedBy(2))
            .truncatedTo(unit);
}
Date.from(roundHalfUp(date.toInstant(), ChronoUnit.MINUTES))