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

How to Count Number of Days Between Two Dates Using the Gregorian Calendar and While Loops

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 来计算每个循环的成本。我如何使这段代码工作?

回答你的问题,你的代码在一个循环后停止的原因是while循环末尾的return语句。此外,如果 dueBackActualDateRented 相同,它将 return 3,根据您的 else 语句。

但是这段代码还有其他一些问题。您正在使用 != 比较 dueBackActualDateRented,这对于对象检查它们是否是完全相同的对象,而不是比较值。您应该使用 equals 方法来比较日期。

从更一般的意义上讲,您使用 GregorianCalendar 而不是 Java 8 的 Date/Time API 是否有特殊原因? 'new' API 更易于使用,您无需编写自己的循环来确定天数之间的差异。您可以查看 https://www.baeldung.com/java-8-date-time-intro 了解更多信息。

tl;博士

数天。

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.
    )
)

详情

正确,应该接受。

正如他指出的那样,您正在使用多年前被 java.time class在 JSR 310 中定义。

GregorianCalendar class is replaced by ZonedDateTime。您应该完全避免使用旧的 classes。但是当需要与尚未更新到 java.time 的旧代码交互时,您可以使用添加到旧 classes.

的新方法进行转换
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,因此如果与其他期望 [=24 的代码混合,您可能需要转换=].

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

BigDecimal

顺便说一句,在实际工作中,千万不要用doubleDoublefloatFloat来换钱。这些类型使用 floating-point technology which trades away accuracy 来获得快速性能。

在任何需要准确性的情况下,例如处理金钱,请仅使用缓慢但准确的 class BigDecimal


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

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

从哪里获得java.time classes?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.