Как посчитать количество дней между двумя датами, используя григорианский календарь и циклы while - PullRequest
0 голосов
/ 26 октября 2018
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 и увеличивает стоимость на 1 доллар за каждый день после даты dueBack. Это не обязательно должно быть в цикле while, но я подумал, что будет проще написать, но я знаю, что если он записан в цикле while, он будет повторяться каждый день, пока ActualDatRented не будет равен дате dueBack и добавьте 1 к стоимости каждой петли. Как мне заставить этот код работать?

Ответы [ 2 ]

0 голосов
/ 27 октября 2018

ТЛ; др

Количество дней.

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

Подробнее

Ответ Рика правильный и должен быть принят.

Как он указал, вы используете ужасные старые классы даты и времени (GregorianCalendar), которые были вытеснены несколько лет назад классами java.time , определенными в JSR 310.

Класс 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

Кстати, в реальной работе никогда не используйте double или Double, ни float, ни Float за деньги. В этих типах используется технология с плавающей точкой , которая меняет точность для достижения высокой производительности.

В любом контексте, где важна точность, например, обработка денег, используйте только медленный, но точный класс BigDecimal.


О java.time

Фреймворк java.time встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и more .

0 голосов
/ 26 октября 2018

Чтобы ответить на ваш вопрос, причиной, по которой ваш код останавливается после одного цикла, является оператор return в конце цикла while.Кроме того, если dueBack совпадает с ActualDateRented, он вернет 3, как указано в вашем операторе else.

Но в этом коде есть и другие проблемы.Вы сравниваете dueBack с ActualDateRented, используя !=, который для объектов проверяет, являются ли они одинаковыми объектами, а не сравнивает значения.Для сравнения дат следует использовать метод equals.

В более общем смысле, есть ли конкретная причина, по которой вы используете GregorianCalendar вместо API даты / времени в Java 8?«Новый» API намного проще в использовании, и вам не нужно писать свои собственные циклы, чтобы определить разницу между днями.Вы можете проверить https://www.baeldung.com/java-8-date-time-intro для получения дополнительной информации.

...