Сделать алгоритм, который считает разницу между дати в днях

Вот само задание

В общем сделал половину, но не могу сообразить как разобраться с датой, прошу помощи.

public class Main {
    public static void main(String[] args) {

        Date mass[] = new Date[3];
        mass[0] = new Date(11, 9, 2020);
        mass[1] = new Date( 2, 6, 2019);
        mass[2] = new Date( 1, 5, 2020);
        for (int i = 0; i < 3; i++)
            mass[i].displayInfo();
        mass[0].days();
        mass[0].Date();
        mass[2].Date();
    }
}
class Date {
    int year, month, day;
    {
        year=2021;
        month=10;
        day=7;
    }

    Date(int day) {
        this.day = day;
    }

    Date(int day,int month) {
        this.day = day;
        this.month = month;
    }

    Date(int day, int month, int year) {
        this.day = day;
        this.month = month;
        this.year = year;
    }

    void displayInfo(){
        if(day < 10 && month < 10) {
            System.out.printf("0%d.0%d.%d\n", day, month, year);
        }
        else if(month < 10){
            System.out.printf("%d.0%d.%d\n", day, month, year);
        }
        else if(day < 10){
            System.out.printf("0%d.%d.%d\n", day, month, year);
        }
        else
            System.out.printf("%d.%d.%d\n", day, month, year);
    }


    public int days(){
        int num = 0, cal = 0, Tot = 365;

        for (int i = 1; i < month; i++) {
            if (i == 2) {
                if (year % 4 == 0)
                    num += 29;
                else
                    num += 28;
            } else if (i == 1 || i == 3 || i == 5 || i == 7
                    || i == 8 || i == 10 || i == 12)
                num += 31;
            else
                num += 30;
        }
        if (Tot != 365) {
            System.out.println("Not valid");
        } else {
            cal = Tot - (day + num);
            System.out.println("Remaining month of Days=" + (num + day));
        }
        return 0;
    }
}

Ответы (1 шт):

Автор решения: Alex Rudenko

Если известно количество дней, прошедших с начала года в текущем году (которые вычисляются в методе Date::days()), то алгоритм расчёта количества дней между двумя датами вполне прост:

  1. Если даты относятся к одному году, то количество дней между ними составит разницу между значениями that.days() - this.days()
  2. Иначе нужно определить меньшую дату from, вычислить для неё количество дней до конца года 365/366 - from.days(), прибавить количество дней для второй даты to и добавить количество дней в каждом году между двумя данными датами, с учётом знака между датами.

Для определения меньшей даты имеет смысл реализовать метод compareTo(Date d) из интерфейса Comparable.

Также нужно корректно реализовать метод isLeapYear() -- как известно, високосный год каждые 4 года считался по юлианскому календарю, а в григорианском календаре года, кратные 100, не являются високосными, если только они не кратны 400.

Методы days() и displayInfo() также следует отрефакторить: первый не реализован корректно (всегда возвращает 0), во втором нужно правильно выбрать формат для вывода нулей перед днём/месяцем "%02d".

Итак, класс Date без избыточных конструкторов может выглядеть так:

class Date implements Comparable<Date> {
    private static final int[] DAYS = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    private static final int TOTAL = 365;

    private final int year, month, day; // сделать поля неизменяемыми
    
    public Date(int d, int m, int y) {
        this.year = y;
        this.month = m;
        this.day = d;
    }
    
    public int getYear() { return year; }
    public int getMonth() { return month; }
    public int getDay() { return day; }
    
    public void print() {
        System.out.println(this);
    }
    
    @Override
    public String toString() {
        return String.format("%02d.%02d.%4d", day, month, year);
    }
        
    public int days() {
        int d = 0;
        for (int m = 1; m < month; m++) {
            d += DAYS[m - 1];
            if (m == 2) {
                d += isLeapYear();
            }
        }
        d += day;
        return d;
    }
    
    public int isLeapYear() {
        return Date.isLeapYear(this.year);
    }
    
    public static int isLeapYear(int y) {
        return y % 400 == 0 || y % 100 != 0 && y % 4 == 0 ? 1 : 0;
    }
        
    @Override
    public int compareTo(Date that) {
        int res = Integer.compare(this.year, that.year);
        if (res == 0) {
            res = Integer.compare(this.month, that.month);
        }
        if (res == 0) {
            res = Integer.compare(this.day, that.day);
        }
        return res;
    }

    public int daysBetween(Date that) {
        System.out.println("Days between: " + this + " and " + that);
// следующие строки можно раскомментировать чтобы сравнить данные вычисления
// с корректными методами в Java Date/Time API
//      LocalDate df = LocalDate.of(this.year, this.month, this.day);
//      LocalDate dt = LocalDate.of(that.year, that.month, that.day);
//      System.out.println("Days between: " + df + " and " + dt + " = " + ChronoUnit.DAYS.between(df, dt));

        if (this.year == that.year) {
            return that.days() - this.days();
        }
        // найти меньшую дату
        Date from = this.compareTo(that) <= 0 ? this : that;
        Date to   = this.compareTo(that) > 0 ? this : that;
        int sign = this.compareTo(that) <= 0 ? 1 : -1;
        
        int d = TOTAL + Date.isLeapYear(from.year) - from.days() + to.days();
        for (int y = from.year + 1; y < to.year; y++) {
            d += TOTAL + Date.isLeapYear(y);
        }
        
        return sign * d;
    }
}

Тесты:

Date arr[] = {
    new Date(11, 9, 2020),
    new Date( 2, 6, 2019),
    new Date( 1, 5, 2020),
};

for (Date d : arr) {
    d.print();
    System.out.println(d.days());
}

System.out.println(arr[0].daysBetween(arr[2]));

Результаты:

11.09.2020
255
02.06.2019
153
01.05.2020
122
Days between: 11.09.2020 and 01.05.2020
-133
→ Ссылка