如何使用公历和While循环计算两个日期之间的天数

时间:2018-10-26 14:04:08

标签: java date while-loop gregorian-calendar

public class DVD implements Serializable {

private static final long serialVersionUID = 1L;
protected GregorianCalendar rentedOn;
protected GregorianCalendar dueBack;
protected String title;
protected String nameOfRenter;

public double getCost(GregorianCalendar ActualDatRented) {
    double cost = 3;
    double count = 0;
    if (ActualDatRented.after(this.dueBack)) {
        while(!dueBack.equals(ActualDatRented)) {
            count++;
            dueBack.add(Calendar.DATE,1);
            cost = cost + count;
            return cost;
        }
    }else if(ActualDatRented.equals(dueBack))
        cost = 3;

    return cost;
  }
}

此代码假设要计算出DueBack和ActualDatRented之间的天数,并在DueBack日期之后的每一天将费用增加$ 1。它不需要处于while循环中,但是我认为编写起来会更容易,但是我确实知道,如果在while循环中编写它,则必须每天循环遍历,直到ActualDatRented等于dueBack日期和将1加到每个循环中。如何使此代码起作用?

2 个答案:

答案 0 :(得分:3)

要回答您的问题,代码在一个循环后停止的原因是while循环结束时的return语句。另外,如果dueBackActualDateRented相同,则按照else语句返回3。

但是此代码还有其他一些错误。您正在使用dueBackActualDateRented!=进行比较,equals用于检查对象是否都是完全相同的对象,而不是比较值。您应该使用GregorianCalendar方法比较日期。

从更一般的意义上讲,您使用session_start(); 而不是Java 8的Date / Time API是否有特定的原因? “新” API易于使用,您无需编写自己的循环来确定两天之间的差额。您可以检查https://www.baeldung.com/java-8-date-time-intro以获得更多信息。

答案 1 :(得分:0)

tl; dr

数天。

ChronoUnit.DAYS.between( 
    myGregorianCalendar_Start.toZonedDateTime().toLocalDate() , 
    myGregorianCalendar_Stop.toZonedDateTime().toLocalDate() 
)

比较。

if( 
     myGregorianCalendar_Start.toZonedDateTime().toLocalDate()
     .isBefore( 
          myGregorianCalendar_Stop.toZonedDateTime().toLocalDate()
     )
) { … }

做数学。 (未经测试的代码,用作概念指南,实际上需要根据业务规则指定四舍五入到一美分或一美分的整数)

new BigDecimal( "3" )  // Base cost.
.add( 
    new BigDecimal(
        ChronoUnit.DAYS.between(  // Calculate days overdue.
            myGregorianCalendar_Start.toZonedDateTime().toLocalDate() , 
            myGregorianCalendar_Stop.toZonedDateTime().toLocalDate() 
         )
    )
    .multiply(
        new BigDecimal( "1.5" )  // Daily overdue fee.
    )
)

详细信息

Answer by Rick是正确的,应该接受。

正如他指出的那样,您使用的是可怕的旧日期时间类(GregorianCalendar),这些类早在几年前就被JSR 310中定义的 java.time 类所取代。

GregorianCalendar类被ZonedDateTime取代。您应该完全避免使用旧类。但是,当需要与尚未更新为 java.time 的旧代码交互时,可以使用添加到旧类中的新方法进行转换。

ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime() ;

然后再次返回。

GregorianCalendar myGregorianCalendar = GregorianCalendar.from( zdt ) ;

手头有一个ZonedDateTime对象,您可以提取仅日期部分,而没有时间和时区。

LocalDate ld = zdt.toLocalDate() ;

使用ChronoUnit枚举计算经过的天数。

long days = ChronoUnit.DAYS.between( ldStart , ldStop ) ;

请注意,结果是long(64位整数),而不是32位的int,因此,如果与期望int的其他代码混合,则可能需要强制转换。

int days = ( int ) ChronoUnit.DAYS.between( ldStart , ldStop ) ;

BigDecimal

在实际工作中,切勿使用doubleDoublefloatFloat来赚钱。这些类型使用floating-point技术trades away accuracy获得快速性能。

在涉及准确性的任何情况下,例如处理资金,请仅使用缓慢但准确的类BigDecimal


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore